UNPKG

processing-js

Version:

For the project website, visit http://processingjs.org

907 lines (863 loc) • 33.1 kB
/** Custom browser faking object for code-validation in automated test settings. **/ module.exports = (function fakeBrowser() { // Processing works with a canvas and the DOM, fake it. // This is enough of the DOM to allow the parser work. var __empty_func__ = function () {}; var __elem_func__ = function() { return elem; }; var navigator = { useragent: true }; // generic HTML element var createElement = function(tag) { return { localName: tag, style: {}, setAttribute: __empty_func__, appendChild: __empty_func__, classList: { add: __empty_func__, remove: __empty_func__, contains: __empty_func__ } }; }; var HTMLCanvasElement = function() {}; // HTML canvas element var Canvas = function() { this.attachEvent = __empty_func__; this.addEventListener = __empty_func__; this.appendChild = __elem_func__; this.removeChild = __empty_func__; this.childNodes = { length: 0 }; this.toDataURL = __empty_func__; this.localName = "canvas"; this.width = 100; this.height = 100; this.getContext = function() { return { translate: __empty_func__, attachEvent: __empty_func__, fillRect: __empty_func__, strokeRect: __empty_func__, fillText: __empty_func__, measureText: function() { return {width:1}; }, clearRect: __empty_func__, beginPath: __empty_func__, moveTo: __empty_func__, lineTo: __empty_func__, rect: __empty_func__, save: __empty_func__, stroke: __empty_func__, fill: __empty_func__, rotate: __empty_func__, closePath: __empty_func__, arc: __empty_func__, scale: __empty_func__, restore: __empty_func__, bezierCurveTo: __empty_func__, viewport: __empty_func__, clearColor: __empty_func__, clear: __empty_func__, enable: __empty_func__, createShader: __empty_func__, shaderSource: __empty_func__, compileShader: __empty_func__, getShaderParameter: function() { return true; }, getShaderInfoLog: __empty_func__, createProgram: __empty_func__, attachShader: __empty_func__, linkProgram: __empty_func__, getProgramParameter: function() { return true; }, useProgram: __empty_func__, createBuffer: __empty_func__, bindBuffer: __empty_func__, bufferData: __empty_func__, blendFunc: __empty_func__, getAttribLocation: __empty_func__, vertexAttribPointer: __empty_func__, enableVertexAttribArray: __empty_func__, getUniformLocation: __empty_func__, uniform1f: __empty_func__, uniform2f: __empty_func__, uniform3f: __empty_func__, uniform4f: __empty_func__, uniformfv: __empty_func__, uniform2fv: __empty_func__, uniform3fv: __empty_func__, uniform1i: __empty_func__, uniform2i: __empty_func__, uniform3i: __empty_func__, uniform4i: __empty_func__, getImageData: function() { return {width:1, height:1, data:[1,2,3,4]}; }, createImageData: function() { return {width:1, height:1, data:[1,2,3,4]}; }, drawImage: __empty_func__, drawElements: __empty_func__, putImageData: __empty_func__, lineWidth: __empty_func__, disable: __empty_func__, drawArrays: __empty_func__, polygonOffset: __empty_func__, createTexture: __empty_func__, texImage2D: __empty_func__, texParameteri: __empty_func__, generateMipmap: __empty_func__, uniformMatrix4fv: __empty_func__, uniform4fv: __empty_func__, disableVertexAttribArray: __empty_func__, bindTexture: __empty_func__, setTransform: __empty_func__ }; }; this.style = { setProperty: __empty_func__ }; this.__attributes = { "data-processing-sources" : "test.pjs" }; this.hasAttribute = function(name) { return this.__attributes.hasOwnProperty(name.toLowerCase()); }; this.getAttribute = function(name) { return this.__attributes[name.toLowerCase()]; }; this.setAttribute = function(name, value) { this.__attributes[name.toLowerCase()] = value; }; }; Canvas.prototype = new HTMLCanvasElement(); var canvas = new Canvas(); var HTMLImageElement = __empty_func__; var document = { fake: true, attachEvent: __empty_func__, head: { appendChild: __elem_func__, removeChild: __empty_func__ }, body: { appendChild: __elem_func__, removeChild: __empty_func__, style: { cursor: {} } }, querySelector: function(selector) { return createElement(selector); }, defaultView: { getComputedStyle: function() { return { getPropertyValue: function() { return ""; } }; } }, appendChild: __elem_func__, removeChild: __empty_func__, getElementById: __empty_func__, getElementsByTagName: function() { return [canvas]; }, createElement: function (tag) { if (tag === "canvas") return new Canvas(); return createElement(tag); }, addEventListener: __empty_func__, documentElement: { appendChild: __elem_func__, removeChild: __empty_func__, style: { paddingBottom: 0 }, insertBefore: __empty_func__ }, createTextNode: __empty_func__ }; var elem = { appendChild: __elem_func__, removeChild: __empty_func__, style: {} }; var addEventListener = __empty_func__; var XMLHttpRequest = __empty_func__; var setInterval = __empty_func__; var clearInterval = __empty_func__; var Image = __empty_func__; var localStorage = __empty_func__; // The XML parser is designed only for parsing of // simple XML documents (for unit testing purpose). function DOMParser() { // parser function parseXml(s, sink) { var i = 0, scopes = [{ space: "default", xmlns: "", namespaces: { "xmlns":"http://www.w3.org/2000/xmlns/", "xml":"http://www.w3.org/XML/1998/namespace" } }]; function unSelfClose(s) { // This code is actually not good at parsing self-closed elements, // so as a preprocess step we "open" self closed elements. return s.replace(/<([a-zA-Z-_]+)[^\/>]*\/>/g, function(a,b) { if(a==="undefined" && b==="undefined") return ''; return a.replace(/\s*\/>/, "></"+b+">"); }); } function trim(s) { return s.replace(/^\s+/, "").replace(/\s+$/, ""); } function resolveEntities(s) { return s.replace(/&([^;]+);/g, function(all, entity) { if (entity.substring(0, 2) === "#x") { return String.fromCharCode(parseInt(entity.substring(2), 16)); } else if(entity.substring(0,1) === "#") { return String.fromCharCode(parseInt(entity.substring(1), 10)); } switch (entity) { case "lt": return "<"; case "gt": return ">"; case "amp": return "&"; } throw "Unknown entity: " + entity; }); } function isWhitespacePreserved() { for (var j = scopes.length - 1; j >= 0; --j) { if (scopes[j].space === "preserve") { return true; } } return false; } function lookupDefaultNs() { for (var j = scopes.length - 1; j >= 0; --j) { if (scopes[j].hasOwnProperty("xmlns")) { return scopes[j].xmlns; } } } function lookupNs(prefix) { for (var j = scopes.length - 1; j >= 0; --j) { if (scopes[j].namespaces.hasOwnProperty(prefix)) { return scopes[j].namespaces[prefix]; } } throw "Unknow namespace: " + prefix; } function getName(name, resolveDefaultNs) { var j = name.indexOf(":"); if (j >= 0) { return {name:name.substring(j + 1), prefix: name.substring(0,j), namespace: lookupNs(name.substring(0,j))}; } else if(resolveDefaultNs) { return {name:name, prefix: "", namespace: lookupDefaultNs()}; } else { return {name:name, prefix: "", namespace: ""}; } } function isWhitespace(s, index) { var ch = s.charCodeAt(index); return ch == 10 || ch == 13 || ch == 9 || ch == 32; } function parseContent(s, start) { var pos = start, name, attributes = []; function skipWs() { while (pos < s.length && isWhitespace(s, pos)) { ++pos; } } while (pos < s.length && !isWhitespace(s, pos) && s.charAt(pos) !== ">") { ++pos; } name = s.substring(start, pos); skipWs(); while (pos < s.length && s.charAt(pos) !== ">" && s.charAt(pos) !== "/" && s.charAt(pos) !== "?") { skipWs(); var attrName = "", attrValue = ""; while (pos < s.length && !isWhitespace(s, pos) && s.charAt(pos) !== "=") { attrName += s.charAt(pos); ++pos; } skipWs(); if (s.charAt(pos) !== "=") throw "'=' expected"; ++pos; skipWs(); var attrEndChar = s.charAt(pos); if (attrEndChar !== "\"" && attrEndChar !== "\'" ) throw "Quote expected"; var attrEndIndex = s.indexOf(attrEndChar, ++pos); if (attrEndIndex < 0) throw "Unexpected EOF[6]"; attrValue = s.substring(pos, attrEndIndex); attributes.push({name: attrName, value: resolveEntities(attrValue)}); pos = attrEndIndex + 1; skipWs(); } return {name: name, attributes: attributes, parsed: pos - start}; } // ================================== // The actual XML parsing starts here // ================================== s = unSelfClose(s); while (i < s.length) { var ch = s.charAt(i); var j = i; var content; if (ch === "<") { ++j; var ch2 = s.charAt(j), q, name; switch (ch2) { case "/": ++j; q = s.indexOf(">", j); if(q < 0) { throw "Unexpected EOF[1]"; } name = getName(s.substring(j,q), true); sink.endElement(name); scopes.pop(); j = q + 1; break; case "?": ++j; content = parseContent(s, j); if (s.substring(j + content.parsed, j + content.parsed + 2) != "?>") { throw "Unexpected EOF[2]"; } sink.pi(content.name, content.attributes); j += content.parsed + 2; break; case "!": if (s.substring(j + 1, j + 3) === "--") { q = s.indexOf("-->", j + 3); if(q < 0) { throw "Unexpected EOF[3]"; } sink.comment(s.substring(j + 3, q)); j = q + 3; } else if (s.substring(j + 1, j + 8) === "[CDATA[") { q = s.indexOf("]]>", j + 8); if(q < 0) { throw "Unexpected EOF[4]"; } sink.cdata(s.substring(j + 8, q)); j = q + 3; } else if (s.substring(j + 1, j + 8) === "DOCTYPE") { var q2 = s.indexOf("[", j + 8), complexDoctype = false; q = s.indexOf(">", j + 8); if(q < 0) { throw "Unexpected EOF[5]"; } if (q2 > 0 && q > q2) { q = s.indexOf("]>", j + 8); if(q < 0) { throw "Unexpected EOF[7]"; } complexDoctype = true; } var doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0)); sink.doctype(doctypeContent); // XXX pull entities ? j = q + (complexDoctype ? 2 : 1); } else { throw "Unknown !tag"; } break; default: content = parseContent(s, j); var isClosed = false; if (s.substring(j + content.parsed, j + content.parsed + 2) === "/>") { isClosed = true; } else if (s.substring(j + content.parsed, j + content.parsed + 1) !== ">") { throw "Unexpected EOF[2]"; } var scope = {namespaces:[]}; for (q = 0; q < content.attributes.length; ++q) { if (content.attributes[q].name.substring(0, 6) === "xmlns:") { scope.namespaces[content.attributes[q].name.substring(6)] = trim(content.attributes[q].value); } else if (content.attributes[q].name === "xmlns") { scope.xmlns = trim(content.attributes[q].value); } else if (content.attributes[q].name.substring(0, 4) === "xml:") { scope[content.attributes[q].name.substring(4)] = trim(content.attributes[q].value); } else if (content.attributes[q].name.substring(0, 3) === "xml") { throw "Invalid xml attribute"; } } scopes.push(scope); var attributes = []; for (q = 0; q < content.attributes.length; ++q) { attributes.push({name: getName(content.attributes[q].name, false), value: content.attributes[q].value}); } sink.beginElement(getName(content.name, true), attributes, isClosed); j += content.parsed + (isClosed ? 2 : 1); if (isClosed) scopes.pop(); break; } } else { do { if (++j >= s.length) break; } while(s.charAt(j) !== "<"); var text = s.substring(i, j); var isWs = text.replace(/^\s+/, "").length === 0; if (!isWs || isWhitespacePreserved()) { sink.text(resolveEntities(text), isWs); } } i = j; } } // end of parser var implementation = this; function NodeList(init) { var nodes = []; if (init) { nodes = nodes.concat(init); } nodes.item = function(index) { return nodes[index]; }; return nodes; } function NamedNodeMap(owner) { var nodes = []; nodes.item = function(index) { return nodes[index]; }; nodes.getNamedItem = function(name) { for (var i = 0; i < nodes.length; ++i) { if (nodes[i].name === name) return nodes[i]; } return null; }; nodes.setNamedItem = function(arg) { for (var i = 0; i < nodes.length; ++i) { if (nodes[i].name === arg.name) { var old = nodes[i]; nodes[i] = arg; old.ownerElement = null; return old; } } arg.ownerElement = owner; nodes.push(arg); return null; }; nodes.removeNamedItem = function(name) { for (var i = 0; i < nodes.length; ++i) { if (nodes[i].name === name) { var old = nodes[i]; nodes.splice(i, 1); old.ownerElement = null; return old; } } return null; }; nodes.getNamedItemNS = function(namespaceURI, localName) { for (var i = 0; i < nodes.length; ++i) { if (nodes[i].localName === localName && nodes[i].namespaceURI === namespaceURI) return nodes[i]; } return null; }; nodes.setNamedItemNS = function(arg) { for (var i = 0; i < nodes.length; ++i) { if (nodes[i].localName === arg.localName && nodes[i].namespaceURI === arg.namespaceURI) { var old = nodes[i]; nodes[i] = arg; old.ownerElement = null; return old; } } arg.ownerElement = owner; nodes.push(arg); return null; }; nodes.removeNamedItemNS = function(namespaceURI, localName) { for (var i = 0; i < nodes.length; ++i) { if (nodes[i].localName === localName && nodes[i].namespaceURI === namespaceURI) { var old = nodes[i]; nodes.splice(i, 1); old.ownerElement = null; return old; } } return null; }; return nodes; } function Node() { this.childNodes = new NodeList(); } Node.ELEMENT_NODE = 1; Node.ATTRIBUTE_NODE = 2; Node.TEXT_NODE = 3; Node.CDATA_SECTION_NODE = 4; Node.ENTITY_REFERENCE_NODE = 5; Node.ENTITY_NODE = 6; Node.PROCESSING_INSTRUCTION_NODE = 7; Node.COMMENT_NODE = 8; Node.DOCUMENT_NODE = 9; Node.DOCUMENT_TYPE_NODE = 10; Node.DOCUMENT_FRAGMENT_NODE = 11; Node.NOTATION_NODE = 12; Node.prototype.nodeName = null; Node.prototype.nodeValue = null; Node.prototype.nodeType = 0; Node.prototype.parentNode = null; //Node.prototype.childNodes = []; Node.prototype.firstChild = null; Node.prototype.lastChild = null; Node.prototype.previousSibling = null; Node.prototype.nextSibling = null; Node.prototype.ownerDocument = null; Node.prototype.attributes = null; Node.prototype.onChildNodesChanged = function() {}; // XXX newChild in tree remove first // XXX document fragment Node.prototype.insertBefore = function(newChild, refChild) { if (!refChild) { return this.appendChild(newChild); } var i = 0; while (i < this.childNodes.length && this.childNodes[i] != refChild) { ++i; } if (!this.childNodes[i]) throw "Ref child not found"; newChild.parentNode = this; newChild.previousSibling = refChild.previousSibling; if (newChild.previousSibling) newChild.previousSibling.nextSibling = newChild; newChild.nextSibling = refChild; refChild.previousSibling = newChild; if (this.firstChild == refChild) this.firstChild = newChild; this.childNodes.splice(i,0,newChild); this.onChildNodesChanged(); return newChild; }; Node.prototype.replaceChild = function(newChild, oldChild) { var i = 0; while (i < this.childNodes.length && this.childNodes[i] != oldChild) { ++i; } if (!this.childNodes[i]) throw "Old child not found"; newChild.parentNode = this; newChild.previousSibling = oldChild.previousSibling; if (newChild.previousSibling) newChild.previousSibling.nextSibling = newChild; newChild.nextSibling = oldChild.nextSibling; if (newChild.nextSibling) newChild.nextSibling.previousSibling = newChild; oldChild.parentNode = null; oldChild.previousSibling = null; oldChild.nextSibling = null; if (this.lastChild == oldChild) this.lastChild = newChild; if (this.firstChild == oldChild) this.firstChild = newChild; this.childNodes[i] = newChild; this.onChildNodesChanged(); return oldChild; }; Node.prototype.removeChild = function(oldChild) { var i = 0; while (i < this.childNodes.length && this.childNodes[i] != oldChild) { ++i; } if (!this.childNodes[i]) throw "Old child not found"; if (this.lastChild == oldChild) this.lastChild = oldChild.previousSibling; if (this.firstChild == oldChild) this.firstChild = oldChild.nextSibling; if (oldChild.nextSibling) oldChild.nextSibling.previousSibling = oldChild.previousSibling; if (oldChild.previousSibling) oldChild.previousSibling.nextSibling = oldChild.nextSibling; oldChild.parentNode = null; oldChild.previousSibling = null; oldChild.nextSibling = null; this.childNodes.splice(i, 1); this.onChildNodesChanged(); return oldChild; }; Node.prototype.appendChild = function(newChild) { newChild.parentNode = this; var lastChild = this.lastChild; if (lastChild) { newChild.nextSibling = lastChild.nextSibling; if (newChild.nextSibling) newChild.nextSibling.previousSibling = newChild; newChild.previousSibling = lastChild; lastChild.nextSibling = newChild; } else { this.firstChild = newChild; newChild.previousSibling = null; newChild.nextSibling = null; } this.lastChild = newChild; this.childNodes.push(newChild); this.onChildNodesChanged(); return newChild; }; Node.prototype.hasChildNodes = function() { return this.childNodes.length > 0; }; Node.prototype.cloneNode = function(deep) { throw "Not implemented"; }; Node.prototype.normalize = function() { var lastWasText = false; for (var i = 0; i < this.childNodes.length; ++i) { if (this.childNodes[i].nodeType == Node.ELEMENT_NODE) { this.childNodes[i].normalize(); } if (this.childNodes[i].nodeType == Node.TEXT_NODE) { if (lastWasText) { this.childNodes[i - 1].appendData(this.childNodes[i].data); this.removeChild(this.childNodes[i]); --i; } lastWasText = true; } else { lastWasText = false; } } }; Node.prototype.isSupported = function(feature, version) { return false; }; Node.prototype.namespaceURI = null; Node.prototype.prefix = null; Node.prototype.localName = null; Node.prototype.hasAttributes = function() { return this.attributes.length > 0; }; Node.prototype.textContent = ""; function Document() { var node = new Node(); node.nodeType = Node.DOCUMENT_NODE; node.doctype = null; node.implementation = implementation; node.documentElement = null; node.createElement = function(tagName) { return node.createElementNS("", tagName); }; node.createTextNode = function(data, nodeTypeOverride) { var text = new Node(); text.nodeType = (nodeTypeOverride ? nodeTypeOverride : Node.TEXT_NODE); text.ownerDocument = node; text.nodeValue = data; Object.defineProperty(text, "data", { get: function() { return this.nodeValue; }, set: function(value) { this.nodeValue = value; }, enumerable: true }); text.data = data; text.length = data.length; text.appendData = function(arg) { this.nodeValue += arg; }; Object.defineProperty(text, "textContent", { get: function() { return this.nodeValue; }, enumerable: true }); // TODO appendData, substringData, etc. return text; }; node.createCDATASection = function(data) { return this.createTextNode(data, Node.CDATA_SECTION_NODE); }; node.createAttribute = function(name) { return node.createAttributeNS("", name); }; node.getElementsByTagName = function(tagName) { return node.getElementsByTagNameNS("", tagName); }; node.createElementNS = function(namespaceURI, qualifiedName) { var element = new Node(); element.nodeType = Node.ELEMENT_NODE; element.ownerDocument = node; element.attributes = new NamedNodeMap(element); element.tagName = qualifiedName; element.nodeName = qualifiedName; var i = qualifiedName.indexOf(":"); element.localName = i < 0 ? qualifiedName : qualifiedName.substring(i + 1); element.prefix = i < 0 ? "" : qualifiedName.substring(0, i); element.namespaceURI = namespaceURI; element.getAttributeNode = function(name) { return this.attributes.getNamedItem(name); }; element.getAttribute = function(name) { var attr = this.getAttributeNode(name); return attr ? attr.value : ""; }; element.setAttributeNode = function(newAttr) { return this.attributes.setNamedItem(newAttr); }; element.setAttribute = function(name, value) { var attr = this.ownerDocument.createAttribute(name); attr.value = value || ""; this.setAttributeNode(attr); }; element.removeAttribute = function(name) { this.attributes.removeNamedItem(name); }; element.removeAttributeNode = function(oldAttr) { return this.attributes.removeNamedItem(oldAttr.name); }; element.hasAttribute = function(name) { return !!this.attributes.getNamedItem(name); }; element.getAttributeNodeNS = function(namespaceURI, localName) { return this.attributes.getNamedItemNS(namespaceURI, localName); }; element.getAttributeNS = function(namespaceURI, localName) { var attr = this.getAttributeNodeNS(namespaceURI, localName); return attr ? attr.value : ""; }; element.setAttributeNodeNS = function(newAttr) { return this.attributes.setNamedItemNS(newAttr); }; element.setAttribute = function(namespaceURI, qualifiedName) { var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName); attr.value = value || ""; this.setAttributeNodeNS(attr); }; element.removeAttributeNS = function(namespaceURI, localName) { this.attributes.removeNamedItemNS(namespaceURI, localName); }; element.removeAttributeNode = function(oldAttr) { return this.attributes.removeNamedItemNS(oldAttr.namespaceNS, oldAttr.localName); }; element.hasAttributeNS = function(namespaceURI, localName) { return !!this.attributes.getNamedItemNS(namespaceURI, localName); }; element.getElementsByTagName = function(name) { return this.getElementsByTagNameNS("", name); }; element.getElementsByTagNameNS = function(namespaceURI, localName) { var q = [this]; var result = []; while (q.length > 0) { var current = q.shift(); if (current.nodeType == Node.ELEMENT_NODE) { if (current.namespaceURI == namespaceURI && current.localName == localName) { result.push(current); } for (var i = 0; i < current.childNodes.length; ++i) { q.push(current.childNodes[i]); } } } return new NodeList(result); }; Object.defineProperty(element, "textContent", { get: function() { var result = ""; for (var i = 0; i < this.childNodes.length; ++i) { result += this.childNodes[i].textContent; } return result; }, enumerable: true }); return element; }; node.createAttributeNS = function(namespaceURI, qualifiedName) { var attr = new Node(); attr.nodeType = Node.ATTRIBUTE_NODE; attr.ownerDocument = node; attr.name = qualifiedName; attr.nodeName = qualifiedName; var i = qualifiedName.indexOf(":"); attr.localName = i < 0 ? qualifiedName : qualifiedName.substring(i + 1); attr.prefix = i < 0 ? "" : qualifiedName.substring(0, i); attr.namespaceURI = namespaceURI; attr.specified = true; attr.nodeValue = null; Object.defineProperty(attr, "value", { get: function() { return this.nodeValue; }, set: function(value) { this.nodeValue = value; }, enumerable: true }); return attr; }; node.getElementsByTagNameNS = function(namespaceURI, localName) { if (!this.documentElement) return null; return this.documentElement.getElementsByTagNameNS(namespaceURI, localName); }; node.getElementById = function(elementId) { if (this.documentElement) return null; var q = [this.documentElement]; while (q.length > 0) { var current = q.shift(); if (current.nodeType == Node.ELEMENT_NODE) { if (current.getAttribute("id") == elementId) return current; for (var i = 0; i < current.childNodes.length; ++i) { q.push(current.childNodes[i]); } } } return null; }; node.onChildNodesChanged = function() { this.documentElement = null; for (var i = 0; i < this.childNodes.length; ++i) { if (this.childNodes[i].nodeType == Node.ELEMENT_NODE) { this.documentElement = this.childNodes[i]; } } }; Object.defineProperty(node, "textContent", { get: function() { return this.documentElement.textContent; }, enumerable: true }); return node; } function buildQualifiedName(name) { return name.prefix ? name.prefix + ":" + name.name : name.name; } this.parseFromString = function(s, mimeType) { var document = new Document(); var elementsStack = [], currentElement = document; parseXml(s, { beginElement: function(name, attrs, isEmpty) { var parent = currentElement; elementsStack.push(parent); currentElement = document.createElementNS(name.namespace, buildQualifiedName(name)); for (var i = 0; i < attrs.length; ++i) { var attr = document.createAttributeNS(attrs[i].name.namespace, buildQualifiedName(attrs[i].name)); attr.value = attrs[i].value; currentElement.attributes.setNamedItem(attr); } parent.appendChild(currentElement); if (isEmpty) { currentElement = elementsStack.pop(); } }, endElement: function(name) { currentElement = elementsStack.pop(); }, text: function(text, isWhitespace) { var node = document.createTextNode(text); currentElement.appendChild(node); }, cdata: function(text) { var node = document.createCDATASection(text); currentElement.appendChild(node); }, comment: function(text) { }, pi: function(name, attrs) { }, doctype: function(text) { } }); document.normalize(); return document; }; } var window = { appendChild: __elem_func__, removeChild: __empty_func__, addEventListener: __empty_func__, setInterval: __empty_func__, DOMParser: DOMParser, open: __empty_func__, document: document, createElement: function() { return elem; }, setTimeout: __empty_func__, clearInterval: __empty_func__, localStorage: {}, // required object types XMLHttpRequest: __empty_func__, HTMLImageElement: HTMLImageElement, HTMLCanvasElement: HTMLCanvasElement }; window.XMLHttpRequest.prototype.open = __empty_func__; window.XMLHttpRequest.prototype.send = __empty_func__; window.XMLHttpRequest.prototype.responseText = "some text"; window.XMLHttpRequest.prototype.setRequestHeader = __empty_func__; window.XMLHttpRequest.prototype.overrideMimeType = __empty_func__; window.XMLHttpRequest.prototype.status = 200; // and return our fake browser object return { isDomPresent: false, navigator: navigator, window: window, document: document, ajax: function(url) { var xhr = new XMLHttpRequest(); xhr.open("GET", url, false); if (xhr.overrideMimeType) { xhr.overrideMimeType("text/plain"); } xhr.setRequestHeader("If-Modified-Since", "Fri, 01 Jan 1960 00:00:00 GMT"); xhr.send(null); // failed request? if (xhr.status !== 200 && xhr.status !== 0) { throw ("XMLHttpRequest failed, status code " + xhr.status); } return xhr.responseText; } }; }());