426945b480
Please note that these changes were done automatically, using `gulp lint --fix`. Given that the major version number was increased, there's a fair number of (primarily whitespace) changes; please see https://prettier.io/blog/2020/03/21/2.0.0.html In order to reduce the size of these changes somewhat, this patch maintains the old "arrowParens" style for now (once mozilla-central updates Prettier we can simply choose the same formatting, assuming it will differ here).
279 lines
6.9 KiB
JavaScript
279 lines
6.9 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
function xmlEncode(s) {
|
|
var i = 0,
|
|
ch;
|
|
s = String(s);
|
|
while (
|
|
i < s.length &&
|
|
(ch = s[i]) !== "&" &&
|
|
ch !== "<" &&
|
|
ch !== '"' &&
|
|
ch !== "\n" &&
|
|
ch !== "\r" &&
|
|
ch !== "\t"
|
|
) {
|
|
i++;
|
|
}
|
|
if (i >= s.length) {
|
|
return s;
|
|
}
|
|
var buf = s.substring(0, i);
|
|
while (i < s.length) {
|
|
ch = s[i++];
|
|
switch (ch) {
|
|
case "&":
|
|
buf += "&";
|
|
break;
|
|
case "<":
|
|
buf += "<";
|
|
break;
|
|
case '"':
|
|
buf += """;
|
|
break;
|
|
case "\n":
|
|
buf += "
";
|
|
break;
|
|
case "\r":
|
|
buf += "
";
|
|
break;
|
|
case "\t":
|
|
buf += "	";
|
|
break;
|
|
default:
|
|
buf += ch;
|
|
break;
|
|
}
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
function DOMElement(name) {
|
|
this.nodeName = name;
|
|
this.childNodes = [];
|
|
this.attributes = {};
|
|
this.textContent = "";
|
|
|
|
if (name === "style") {
|
|
this.sheet = {
|
|
cssRules: [],
|
|
insertRule: function (rule) {
|
|
this.cssRules.push(rule);
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
DOMElement.prototype = {
|
|
getAttribute: function DOMElement_getAttribute(name) {
|
|
if (name in this.attributes) {
|
|
return this.attributes[name];
|
|
}
|
|
return null;
|
|
},
|
|
|
|
getAttributeNS: function DOMElement_getAttributeNS(NS, name) {
|
|
// Fast path
|
|
if (name in this.attributes) {
|
|
return this.attributes[name];
|
|
}
|
|
// Slow path - used by test/unit/display_svg_spec.js
|
|
// Assuming that there is only one matching attribute for a given name,
|
|
// across all namespaces.
|
|
if (NS) {
|
|
var suffix = ":" + name;
|
|
for (var fullName in this.attributes) {
|
|
if (fullName.slice(-suffix.length) === suffix) {
|
|
return this.attributes[fullName];
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
setAttribute: function DOMElement_setAttribute(name, value) {
|
|
value = value || "";
|
|
value = xmlEncode(value);
|
|
this.attributes[name] = value;
|
|
},
|
|
|
|
setAttributeNS: function DOMElement_setAttributeNS(NS, name, value) {
|
|
this.setAttribute(name, value);
|
|
},
|
|
|
|
appendChild: function DOMElement_appendChild(element) {
|
|
var childNodes = this.childNodes;
|
|
if (!childNodes.includes(element)) {
|
|
childNodes.push(element);
|
|
}
|
|
},
|
|
|
|
hasChildNodes: function DOMElement_hasChildNodes() {
|
|
return this.childNodes.length !== 0;
|
|
},
|
|
|
|
cloneNode: function DOMElement_cloneNode() {
|
|
var newNode = new DOMElement(this.nodeName);
|
|
newNode.childNodes = this.childNodes;
|
|
newNode.attributes = this.attributes;
|
|
newNode.textContent = this.textContent;
|
|
return newNode;
|
|
},
|
|
|
|
// This method is offered for convenience. It is recommended to directly use
|
|
// getSerializer because that allows you to process the chunks as they come
|
|
// instead of requiring the whole image to fit in memory.
|
|
toString: function DOMElement_toString() {
|
|
var buf = [];
|
|
var serializer = this.getSerializer();
|
|
var chunk;
|
|
while ((chunk = serializer.getNext()) !== null) {
|
|
buf.push(chunk);
|
|
}
|
|
return buf.join("");
|
|
},
|
|
|
|
getSerializer: function DOMElement_getSerializer() {
|
|
return new DOMElementSerializer(this);
|
|
},
|
|
};
|
|
|
|
function DOMElementSerializer(node) {
|
|
this._node = node;
|
|
this._state = 0;
|
|
this._loopIndex = 0;
|
|
this._attributeKeys = null;
|
|
this._childSerializer = null;
|
|
}
|
|
DOMElementSerializer.prototype = {
|
|
/**
|
|
* Yields the next chunk in the serialization of the element.
|
|
*
|
|
* @returns {string|null} null if the element has fully been serialized.
|
|
*/
|
|
getNext: function DOMElementSerializer_getNext() {
|
|
var node = this._node;
|
|
switch (this._state) {
|
|
case 0: // Start opening tag.
|
|
++this._state;
|
|
return "<" + node.nodeName;
|
|
case 1: // Add SVG namespace if this is the root element.
|
|
++this._state;
|
|
if (node.nodeName === "svg:svg") {
|
|
return (
|
|
' xmlns:xlink="http://www.w3.org/1999/xlink"' +
|
|
' xmlns:svg="http://www.w3.org/2000/svg"'
|
|
);
|
|
}
|
|
/* falls through */
|
|
case 2: // Initialize variables for looping over attributes.
|
|
++this._state;
|
|
this._loopIndex = 0;
|
|
this._attributeKeys = Object.keys(node.attributes);
|
|
/* falls through */
|
|
case 3: // Serialize any attributes and end opening tag.
|
|
if (this._loopIndex < this._attributeKeys.length) {
|
|
var name = this._attributeKeys[this._loopIndex++];
|
|
return " " + name + '="' + xmlEncode(node.attributes[name]) + '"';
|
|
}
|
|
++this._state;
|
|
return ">";
|
|
case 4: // Serialize textContent for tspan/style elements.
|
|
if (node.nodeName === "svg:tspan" || node.nodeName === "svg:style") {
|
|
this._state = 6;
|
|
return xmlEncode(node.textContent);
|
|
}
|
|
++this._state;
|
|
this._loopIndex = 0;
|
|
/* falls through */
|
|
case 5: // Serialize child nodes (only for non-tspan/style elements).
|
|
var value;
|
|
while (true) {
|
|
value = this._childSerializer && this._childSerializer.getNext();
|
|
if (value !== null) {
|
|
return value;
|
|
}
|
|
var nextChild = node.childNodes[this._loopIndex++];
|
|
if (nextChild) {
|
|
this._childSerializer = new DOMElementSerializer(nextChild);
|
|
} else {
|
|
this._childSerializer = null;
|
|
++this._state;
|
|
break;
|
|
}
|
|
}
|
|
/* falls through */
|
|
case 6: // Ending tag.
|
|
++this._state;
|
|
return "</" + node.nodeName + ">";
|
|
case 7: // Done.
|
|
return null;
|
|
default:
|
|
throw new Error("Unexpected serialization state: " + this._state);
|
|
}
|
|
},
|
|
};
|
|
|
|
const document = {
|
|
childNodes: [],
|
|
|
|
get currentScript() {
|
|
return { src: "" };
|
|
},
|
|
|
|
get documentElement() {
|
|
return this;
|
|
},
|
|
|
|
createElementNS: function (NS, element) {
|
|
var elObject = new DOMElement(element);
|
|
return elObject;
|
|
},
|
|
|
|
createElement: function (element) {
|
|
return this.createElementNS("", element);
|
|
},
|
|
|
|
getElementsByTagName: function (element) {
|
|
if (element === "head") {
|
|
return [this.head || (this.head = new DOMElement("head"))];
|
|
}
|
|
return [];
|
|
},
|
|
};
|
|
|
|
function Image() {
|
|
this._src = null;
|
|
this.onload = null;
|
|
}
|
|
Image.prototype = {
|
|
get src() {
|
|
return this._src;
|
|
},
|
|
set src(value) {
|
|
this._src = value;
|
|
if (this.onload) {
|
|
this.onload();
|
|
}
|
|
},
|
|
};
|
|
|
|
exports.document = document;
|
|
exports.Image = Image;
|
|
|
|
var exported_symbols = Object.keys(exports);
|
|
|
|
exports.setStubs = function (namespace) {
|
|
exported_symbols.forEach(function (key) {
|
|
console.assert(!(key in namespace), "property should not be set: " + key);
|
|
namespace[key] = exports[key];
|
|
});
|
|
};
|
|
exports.unsetStubs = function (namespace) {
|
|
exported_symbols.forEach(function (key) {
|
|
console.assert(key in namespace, "property should be set: " + key);
|
|
delete namespace[key];
|
|
});
|
|
};
|