From 34f553940cd5e9fba5ca6062333f42ba741b700a Mon Sep 17 00:00:00 2001 From: nanalelfe Date: Sun, 24 Jul 2016 23:14:34 -0400 Subject: Fixed /send_message error/success message show up. --- node_modules/jsdom/lib/README.md | 17 + node_modules/jsdom/lib/jsdom.js | 379 ++++ node_modules/jsdom/lib/jsdom/browser/Window.js | 291 +++ .../jsdom/lib/jsdom/browser/documentAdapter.js | 62 + .../jsdom/lib/jsdom/browser/documentfeatures.js | 52 + node_modules/jsdom/lib/jsdom/browser/domtohtml.js | 24 + node_modules/jsdom/lib/jsdom/browser/history.js | 94 + node_modules/jsdom/lib/jsdom/browser/htmltodom.js | 231 +++ node_modules/jsdom/lib/jsdom/browser/index.js | 85 + node_modules/jsdom/lib/jsdom/browser/location.js | 103 + node_modules/jsdom/lib/jsdom/browser/utils.js | 15 + node_modules/jsdom/lib/jsdom/contextify-shim.js | 53 + node_modules/jsdom/lib/jsdom/level1/core.js | 1794 ++++++++++++++++ node_modules/jsdom/lib/jsdom/level2/core.js | 306 +++ node_modules/jsdom/lib/jsdom/level2/events.js | 441 ++++ node_modules/jsdom/lib/jsdom/level2/html.js | 2140 ++++++++++++++++++++ .../jsdom/lib/jsdom/level2/languages/javascript.js | 13 + node_modules/jsdom/lib/jsdom/level2/style.js | 263 +++ node_modules/jsdom/lib/jsdom/level3/core.js | 597 ++++++ node_modules/jsdom/lib/jsdom/level3/ls.js | 211 ++ node_modules/jsdom/lib/jsdom/level3/xpath.js | 1866 +++++++++++++++++ .../jsdom/lib/jsdom/living/character-data.js | 90 + node_modules/jsdom/lib/jsdom/living/comment.js | 13 + .../jsdom/lib/jsdom/living/document-type.js | 19 + node_modules/jsdom/lib/jsdom/living/document.js | 26 + .../jsdom/lib/jsdom/living/dom-implementation.js | 85 + .../lib/jsdom/living/helpers/validate-names.js | 63 + node_modules/jsdom/lib/jsdom/living/index.js | 23 + node_modules/jsdom/lib/jsdom/living/node-filter.js | 47 + node_modules/jsdom/lib/jsdom/living/node.js | 261 +++ .../lib/jsdom/living/processing-instruction.js | 15 + node_modules/jsdom/lib/jsdom/living/selectors.js | 32 + node_modules/jsdom/lib/jsdom/living/text.js | 41 + node_modules/jsdom/lib/jsdom/utils.js | 223 ++ node_modules/jsdom/lib/jsdom/virtual-console.js | 24 + 35 files changed, 9999 insertions(+) create mode 100644 node_modules/jsdom/lib/README.md create mode 100644 node_modules/jsdom/lib/jsdom.js create mode 100644 node_modules/jsdom/lib/jsdom/browser/Window.js create mode 100644 node_modules/jsdom/lib/jsdom/browser/documentAdapter.js create mode 100644 node_modules/jsdom/lib/jsdom/browser/documentfeatures.js create mode 100644 node_modules/jsdom/lib/jsdom/browser/domtohtml.js create mode 100644 node_modules/jsdom/lib/jsdom/browser/history.js create mode 100644 node_modules/jsdom/lib/jsdom/browser/htmltodom.js create mode 100644 node_modules/jsdom/lib/jsdom/browser/index.js create mode 100644 node_modules/jsdom/lib/jsdom/browser/location.js create mode 100644 node_modules/jsdom/lib/jsdom/browser/utils.js create mode 100644 node_modules/jsdom/lib/jsdom/contextify-shim.js create mode 100644 node_modules/jsdom/lib/jsdom/level1/core.js create mode 100644 node_modules/jsdom/lib/jsdom/level2/core.js create mode 100644 node_modules/jsdom/lib/jsdom/level2/events.js create mode 100644 node_modules/jsdom/lib/jsdom/level2/html.js create mode 100644 node_modules/jsdom/lib/jsdom/level2/languages/javascript.js create mode 100644 node_modules/jsdom/lib/jsdom/level2/style.js create mode 100644 node_modules/jsdom/lib/jsdom/level3/core.js create mode 100644 node_modules/jsdom/lib/jsdom/level3/ls.js create mode 100644 node_modules/jsdom/lib/jsdom/level3/xpath.js create mode 100644 node_modules/jsdom/lib/jsdom/living/character-data.js create mode 100644 node_modules/jsdom/lib/jsdom/living/comment.js create mode 100644 node_modules/jsdom/lib/jsdom/living/document-type.js create mode 100644 node_modules/jsdom/lib/jsdom/living/document.js create mode 100644 node_modules/jsdom/lib/jsdom/living/dom-implementation.js create mode 100644 node_modules/jsdom/lib/jsdom/living/helpers/validate-names.js create mode 100644 node_modules/jsdom/lib/jsdom/living/index.js create mode 100644 node_modules/jsdom/lib/jsdom/living/node-filter.js create mode 100644 node_modules/jsdom/lib/jsdom/living/node.js create mode 100644 node_modules/jsdom/lib/jsdom/living/processing-instruction.js create mode 100644 node_modules/jsdom/lib/jsdom/living/selectors.js create mode 100644 node_modules/jsdom/lib/jsdom/living/text.js create mode 100644 node_modules/jsdom/lib/jsdom/utils.js create mode 100644 node_modules/jsdom/lib/jsdom/virtual-console.js (limited to 'node_modules/jsdom/lib') diff --git a/node_modules/jsdom/lib/README.md b/node_modules/jsdom/lib/README.md new file mode 100644 index 0000000..8f0856c --- /dev/null +++ b/node_modules/jsdom/lib/README.md @@ -0,0 +1,17 @@ +# Note: this codebase is in a transitional state + +We're slowly moving from a historical model based on layered "levels" of specs, to the [living standard model](https://wiki.whatwg.org/wiki/FAQ#What_does_.22Living_Standard.22_mean.3F) actually implemented by browsers. As such, the code is kind of a mess. + +**Summary**: new features go in `lib/jsdom/living` and follow the code style there; modifications to existing features will require some spelunking to find out what to modify in-place. + +--- + +A lot of the main implementation is in `lib/jsdom/level1` and `lib/jsdom/level2`. (That includes things that didn't appear in the original DOM Level 1 and Level 2 specs, just because the code was located there and we had to patch it.) We're trying to avoid adding new code there, but patching old code is often still required. + +New features generally go in the `lib/jsdom/living` folder, in nice small files, with a clear coding style enforced by JSHint. + +We're planning to fix this whole situation with a multi-stage process: + +- First, consolidate any leftovers in `lib/jsdom/browser` and `lib/jsdom/level3`, as well as the more substantial body of code in `lib/jsdom/level2`, into `lib/jsdom/level1`. This will contain the "historical" portion of the jsdom codebase. +- Then, embark on a major cleanup and refactoring effort, splitting out small pieces from `lib/jsdom/level1` and into `lib/jsdom/living`, cleaning up the code style and spec compliance as we go. +- Finally, collapse the silly directory hierarchy into something less nested. diff --git a/node_modules/jsdom/lib/jsdom.js b/node_modules/jsdom/lib/jsdom.js new file mode 100644 index 0000000..e801634 --- /dev/null +++ b/node_modules/jsdom/lib/jsdom.js @@ -0,0 +1,379 @@ +var fs = require('fs'); +var path = require('path'); +var URL = require('url'); + +var toFileUrl = require('./jsdom/utils').toFileUrl; +var defineGetter = require('./jsdom/utils').defineGetter; +var defineSetter = require('./jsdom/utils').defineSetter; +var features = require('./jsdom/browser/documentfeatures'); +var dom = require('./jsdom/living'); +var browserAugmentation = require('./jsdom/browser/index').browserAugmentation; +var domToHtml = require('./jsdom/browser/domtohtml').domToHtml; +var VirtualConsole = require('./jsdom/virtual-console'); + +var canReadFilesFromFS = !!fs.readFile; // in a browserify environment, this isn't present + +var request = function() { // lazy loading request + request = require('request'); + return request.apply(undefined, arguments); +} + +exports.getVirtualConsole = function (window) { + return window._virtualConsole; +}; +exports.debugMode = false; + +// Proxy feature functions to features module. +['availableDocumentFeatures', + 'defaultDocumentFeatures', + 'applyDocumentFeatures'].forEach(function (propName) { + defineGetter(exports, propName, function () { + return features[propName]; + }); + defineSetter(exports, propName, function (val) { + return features[propName] = val; + }); +}); + +exports.jsdom = function (html, options) { + if (options === undefined) { + options = {}; + } + if (options.parsingMode === undefined || options.parsingMode === 'auto') { + options.parsingMode = 'html'; + } + + var browser = browserAugmentation(dom, options); + var doc = new browser.HTMLDocument(options); + + if (options.created) { + options.created(null, doc.parentWindow); + } + + features.applyDocumentFeatures(doc, options.features); + + if (html === undefined) { + html = ''; + } + html = String(html); + doc.write(html); + + if (doc.close && !options.deferClose) { + doc.close(); + } + + return doc; +}; + +exports.jQueryify = exports.jsdom.jQueryify = function (window, jqueryUrl, callback) { + if (!window || !window.document) { + return; + } + + var features = window.document.implementation._features; + window.document.implementation._addFeature('FetchExternalResources', ['script']); + window.document.implementation._addFeature('ProcessExternalResources', ['script']); + window.document.implementation._addFeature('MutationEvents', ['2.0']); + + var scriptEl = window.document.createElement('script'); + scriptEl.className = 'jsdom'; + scriptEl.src = jqueryUrl; + scriptEl.onload = scriptEl.onerror = function () { + window.document.implementation._features = features; + + if (callback) { + callback(window, window.jQuery); + } + }; + + window.document.body.appendChild(scriptEl); +}; + +exports.env = exports.jsdom.env = function () { + var config = getConfigFromArguments(arguments); + + if (config.file && canReadFilesFromFS) { + fs.readFile(config.file, 'utf-8', function (err, text) { + if (err) { + if (config.created) { + config.created(err); + } + if (config.done) { + config.done([err]); + } + return; + } + + setParsingModeFromExtension(config, config.file); + + config.html = text; + processHTML(config); + }); + } else if (config.html !== undefined) { + processHTML(config); + } else if (config.url) { + handleUrl(config); + } else if (config.somethingToAutodetect !== undefined) { + var url = URL.parse(config.somethingToAutodetect); + if (url.protocol && url.hostname) { + config.url = config.somethingToAutodetect; + handleUrl(config.somethingToAutodetect); + } else if (canReadFilesFromFS) { + fs.readFile(config.somethingToAutodetect, 'utf-8', function (err, text) { + if (err) { + // the toString() test is because in Node.js, there is no proper code for this. + // This is fixed in io.js: https://github.com/iojs/io.js/issues/517 so: + // TODO: remove when we start requiring io.js + if (err.code === 'ENOENT' || err.code === 'ENAMETOOLONG' + || (err.toString() == 'Error: Path must be a string without null bytes.') + ) { + config.html = config.somethingToAutodetect; + processHTML(config); + } else { + if (config.created) { + config.created(err); + } + if (config.done) { + config.done([err]); + } + } + } else { + setParsingModeFromExtension(config, config.somethingToAutodetect); + + config.html = text; + config.url = toFileUrl(config.somethingToAutodetect); + processHTML(config); + } + }); + } else { + config.html = config.somethingToAutodetect; + processHTML(config); + } + } + + function handleUrl() { + var options = { + uri: config.url, + encoding: config.encoding || 'utf8', + headers: config.headers || {}, + proxy: config.proxy || null, + jar: config.jar !== undefined ? config.jar : true + }; + + request(options, function (err, res, responseText) { + if (err) { + if (config.created) { + config.created(err); + } + if (config.done) { + config.done([err]); + } + return; + } + + // The use of `res.request.uri.href` ensures that `window.location.href` + // is updated when `request` follows redirects. + config.html = responseText; + config.url = res.request.uri.href; + + if (config.parsingMode === "auto" && ( + res.headers["content-type"] === "application/xml" || + res.headers["content-type"] === "text/xml" || + res.headers["content-type"] === "application/xhtml+xml")) { + config.parsingMode = "xml"; + } + + processHTML(config); + }); + } +}; + +exports.serializeDocument = function (doc) { + return domToHtml(doc, true); +}; + +function processHTML(config) { + var options = { + features: config.features, + url: config.url, + parser: config.parser, + parsingMode: config.parsingMode, + created: config.created, + resourceLoader: config.resourceLoader + }; + + if (config.document) { + options.referrer = config.document.referrer; + options.cookie = config.document.cookie; + options.cookieDomain = config.document.cookieDomain; + } + + var window = exports.jsdom(config.html, options).parentWindow; + var features = JSON.parse(JSON.stringify(window.document.implementation._features)); + + var docsLoaded = 0; + var totalDocs = config.scripts.length + config.src.length; + var readyState = null; + var errors = []; + + if (!window || !window.document) { + if (config.created) { + config.created(new Error('JSDOM: a window object could not be created.')); + } + if (config.done) { + config.done([new Error('JSDOM: a window object could not be created.')]); + } + return; + } + + window.document.implementation._addFeature('FetchExternalResources', ['script']); + window.document.implementation._addFeature('ProcessExternalResources', ['script']); + window.document.implementation._addFeature('MutationEvents', ['2.0']); + + function scriptComplete() { + docsLoaded++; + + if (docsLoaded >= totalDocs) { + window.document.implementation._features = features; + + errors = errors.concat(window.document.errors || []); + if (errors.length === 0) { + errors = null; + } + + process.nextTick(function() { + if (config.loaded) { + config.loaded(errors, window); + } + if (config.done) { + config.done(errors, window); + } + }); + } + } + + function handleScriptError(e) { + if (!errors) { + errors = []; + } + errors.push(e.error || e.message); + + // nextTick so that an exception within scriptComplete won't cause + // another script onerror (which would be an infinite loop) + process.nextTick(scriptComplete); + } + + if (config.scripts.length > 0 || config.src.length > 0) { + config.scripts.forEach(function (scriptSrc) { + var script = window.document.createElement('script'); + script.className = 'jsdom'; + script.onload = scriptComplete; + script.onerror = handleScriptError; + script.src = scriptSrc; + + try { + // protect against invalid dom + // ex: http://www.google.com/foo#bar + window.document.documentElement.appendChild(script); + } catch (e) { + handleScriptError(e); + } + }); + + config.src.forEach(function (scriptText) { + var script = window.document.createElement('script'); + script.onload = scriptComplete; + script.onerror = handleScriptError; + script.text = scriptText; + + window.document.documentElement.appendChild(script); + window.document.documentElement.removeChild(script); + }); + } else { + if (window.document.readyState === 'complete') { + scriptComplete(); + } else { + window.addEventListener('load', function() { + scriptComplete(); + }); + } + } +} + +function getConfigFromArguments(args, callback) { + var config = {}; + if (typeof args[0] === 'object') { + var configToClone = args[0]; + Object.keys(configToClone).forEach(function (key) { + config[key] = configToClone[key]; + }); + } else { + var stringToAutodetect = null; + + Array.prototype.forEach.call(args, function (arg) { + switch (typeof arg) { + case 'string': + config.somethingToAutodetect = arg; + break; + case 'function': + config.done = arg; + break; + case 'object': + if (Array.isArray(arg)) { + config.scripts = arg; + } else { + extend(config, arg); + } + break; + } + }); + } + + if (!config.done && !config.created && !config.loaded) { + throw new Error('Must pass a "created", "loaded", "done" option or a callback to jsdom.env.'); + } + + if (config.somethingToAutodetect === undefined && + config.html === undefined && !config.file && !config.url) { + throw new Error('Must pass a "html", "file", or "url" option, or a string, to jsdom.env'); + } + + config.scripts = ensureArray(config.scripts); + config.src = ensureArray(config.src); + config.parsingMode = config.parsingMode || "auto"; + + config.features = config.features || { + FetchExternalResources: false, + ProcessExternalResources: false, + SkipExternalResources: false + }; + + if (!config.url && config.file) { + config.url = toFileUrl(config.file); + } + + return config; +} + +function ensureArray(value) { + var array = value || []; + if (typeof array === 'string') { + array = [array]; + } + return array; +} + +function extend(config, overrides) { + Object.keys(overrides).forEach(function (key) { + config[key] = overrides[key]; + }); +} + +function setParsingModeFromExtension(config, filename) { + if (config.parsingMode === "auto") { + var ext = path.extname(filename); + if (ext === ".xhtml" || ext === ".xml") { + config.parsingMode = "xml"; + } + } +} diff --git a/node_modules/jsdom/lib/jsdom/browser/Window.js b/node_modules/jsdom/lib/jsdom/browser/Window.js new file mode 100644 index 0000000..1cee5cb --- /dev/null +++ b/node_modules/jsdom/lib/jsdom/browser/Window.js @@ -0,0 +1,291 @@ +"use strict"; + +var URL = require("url"); +var CSSStyleDeclaration = require("cssstyle").CSSStyleDeclaration; +var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; +var dom = require("../level1/core"); +var NOT_IMPLEMENTED = require("./utils").NOT_IMPLEMENTED; +var createFrom = require("../utils").createFrom; +var History = require("./history"); +var VirtualConsole = require("../virtual-console"); + +var cssSelectorSplitRE = /((?:[^,"']|"[^"]*"|'[^']*')+)/; + +function matchesDontThrow(el, selector) { + try { + return el.matches(selector); + } catch (e) { + return false; + } +} + +function startTimer(window, startFn, stopFn, callback, ms) { + var res = startFn(callback, ms); + window.__timers.push([res, stopFn]); + return res; +} + +function stopTimer(window, id) { + if (typeof id === "undefined") { + return; + } + for (var i in window.__timers) { + if (window.__timers[i][0] === id) { + window.__timers[i][1].call(window, id); + window.__timers.splice(i, 1); + break; + } + } +} + +function stopAllTimers(window) { + window.__timers.forEach(function (t) { + t[1].call(window, t[0]); + }); + window.__timers = []; +} + +function Window(document) { + this.__timers = []; + + // TODO: very little of this belongs on the instance; they should be prototype methods instead. + + var window = this; + this._document = document; + this.history = new History(this); + + this.addEventListener = function () { + dom.Node.prototype.addEventListener.apply(window, arguments); + }; + this.removeEventListener = function () { + dom.Node.prototype.removeEventListener.apply(window, arguments); + }; + this.dispatchEvent = function () { + dom.Node.prototype.dispatchEvent.apply(window, arguments); + }; + this.raise = function () { + dom.Node.prototype.raise.apply(window.document, arguments); + }; + + this.setTimeout = function (fn, ms) { return startTimer(window, setTimeout, clearTimeout, fn, ms); }; + this.setInterval = function (fn, ms) { return startTimer(window, setInterval, clearInterval, fn, ms); }; + this.clearInterval = stopTimer.bind(this, window); + this.clearTimeout = stopTimer.bind(this, window); + this.__stopAllTimers = stopAllTimers.bind(this, window); + this.Image = function (width, height) { + var element = window._document.createElement("img"); + element.width = width; + element.height = height; + return element; + }; + + this._virtualConsole = new VirtualConsole(); + + function wrapConsoleMethod(method) { + return function () { + var args = Array.prototype.slice.call(arguments); + window._virtualConsole.emit.apply(window._virtualConsole, [method].concat(args)); + }; + } + + this.console = { + assert: wrapConsoleMethod("assert"), + clear: wrapConsoleMethod("clear"), + count: wrapConsoleMethod("count"), + debug: wrapConsoleMethod("debug"), + error: wrapConsoleMethod("error"), + group: wrapConsoleMethod("group"), + groupCollapse: wrapConsoleMethod("groupCollapse"), + groupEnd: wrapConsoleMethod("groupEnd"), + info: wrapConsoleMethod("info"), + log: wrapConsoleMethod("log"), + table: wrapConsoleMethod("table"), + time: wrapConsoleMethod("time"), + timeEnd: wrapConsoleMethod("timeEnd"), + trace: wrapConsoleMethod("trace"), + warn: wrapConsoleMethod("warn") + }; + + this.XMLHttpRequest = function () { + var xhr = new XMLHttpRequest(); + var lastUrl = ""; + xhr._open = xhr.open; + xhr.open = function (method, url, async, user, password) { + url = URL.resolve(window.document.URL, url); + lastUrl = url; + return xhr._open(method, url, async, user, password); + }; + xhr._send = xhr.send; + xhr.send = function (data) { + if (window.document.cookie) { + var cookieDomain = window.document._cookieDomain; + var url = URL.parse(lastUrl); + var host = url.host.split(":")[0]; + if (host.indexOf(cookieDomain, host.length - cookieDomain.length) !== -1) { + xhr.setDisableHeaderCheck(true); + xhr.setRequestHeader("cookie", window.document.cookie); + xhr.setDisableHeaderCheck(false); + } + } + return xhr._send(data); + }; + return xhr; + }; +} + +Window.prototype = createFrom(dom || null, { + constructor: Window, + // This implements window.frames.length, since window.frames returns a + // self reference to the window object. This value is incremented in the + // HTMLFrameElement init function (see: level2/html.js). + _length: 0, + get length() { + return this._length; + }, + get document() { + return this._document; + }, + get location() { + return this._document._location; + }, + close: function () { + // Recursively close child frame windows, then ourselves. + var currentWindow = this; + (function windowCleaner(window) { + var i; + // We could call window.frames.length etc, but window.frames just points + // back to window. + if (window.length > 0) { + for (i = 0; i < window.length; i++) { + windowCleaner(window[i]); + } + } + // We"re already in our own window.close(). + if (window !== currentWindow) { + window.close(); + } + })(this); + + if (this._document) { + if (this._document.body) { + this._document.body.innerHTML = ""; + } + + if (this._document.close) { + // We need to empty out the event listener array because + // document.close() causes "load" event to re-fire. + this._document._listeners = []; + this._document.close(); + } + delete this._document; + } + + stopAllTimers(currentWindow); + // Clean up the window"s execution context. + // dispose() is added by Contextify. + this.dispose(); + }, + getComputedStyle: function (node) { + var s = node.style, + cs = new CSSStyleDeclaration(), + forEach = Array.prototype.forEach; + + function setPropertiesFromRule(rule) { + if (!rule.selectorText) { + return; + } + + var selectors = rule.selectorText.split(cssSelectorSplitRE); + var matched = false; + selectors.forEach(function (selectorText) { + if (selectorText !== "" && selectorText !== "," && !matched && matchesDontThrow(node, selectorText)) { + matched = true; + forEach.call(rule.style, function (property) { + cs.setProperty(property, rule.style.getPropertyValue(property), rule.style.getPropertyPriority(property)); + }); + } + }); + } + + forEach.call(node.ownerDocument.styleSheets, function (sheet) { + forEach.call(sheet.cssRules, function (rule) { + if (rule.media) { + if (Array.prototype.indexOf.call(rule.media, "screen") !== -1) { + forEach.call(rule.cssRules, setPropertiesFromRule); + } + } else { + setPropertiesFromRule(rule); + } + }); + }); + + forEach.call(s, function (property) { + cs.setProperty(property, s.getPropertyValue(property), s.getPropertyPriority(property)); + }); + + return cs; + }, + + // TODO: all of the below data properties should be getters; right now they are shared between Window instances + // which is of course bad. + navigator: { + get userAgent() { return "Node.js (" + process.platform + "; U; rv:" + process.version + ")"; }, + get appName() { return "Node.js jsDom"; }, + get platform() { return process.platform; }, + get appVersion() { return process.version; }, + noUI: true, + get cookieEnabled() { return true; } + }, + + name: "nodejs", + innerWidth: 1024, + innerHeight: 768, + outerWidth: 1024, + outerHeight: 768, + pageXOffset: 0, + pageYOffset: 0, + screenX: 0, + screenY: 0, + screenLeft: 0, + screenTop: 0, + scrollX: 0, + scrollY: 0, + scrollTop: 0, + scrollLeft: 0, + alert: NOT_IMPLEMENTED("window.alert"), + blur: NOT_IMPLEMENTED("window.blur"), + confirm: NOT_IMPLEMENTED("window.confirm"), + createPopup: NOT_IMPLEMENTED("window.createPopup"), + focus: NOT_IMPLEMENTED("window.focus"), + moveBy: NOT_IMPLEMENTED("window.moveBy"), + moveTo: NOT_IMPLEMENTED("window.moveTo"), + open: NOT_IMPLEMENTED("window.open"), + print: NOT_IMPLEMENTED("window.print"), + prompt: NOT_IMPLEMENTED("window.prompt"), + resizeBy: NOT_IMPLEMENTED("window.resizeBy"), + resizeTo: NOT_IMPLEMENTED("window.resizeTo"), + scroll: NOT_IMPLEMENTED("window.scroll"), + scrollBy: NOT_IMPLEMENTED("window.scrollBy"), + scrollTo: NOT_IMPLEMENTED("window.scrollTo"), + screen: { + width: 0, + height: 0 + }, + + // Note: these will not be necessary for newer Node.js versions, which have + // typed arrays in V8 and thus on every global object. (That is, in newer + // versions we"ll get `ArrayBuffer` just as automatically as we get + // `Array`.) But to support older versions, we explicitly set them here. + Int8Array: global.Int8Array, + Int16Array: global.Int16Array, + Int32Array: global.Int32Array, + Float32Array: global.Float32Array, + Float64Array: global.Float64Array, + Uint8Array: global.Uint8Array, + Uint8ClampedArray: global.Uint8ClampedArray, + Uint16Array: global.Uint16Array, + Uint32Array: global.Uint32Array, + ArrayBuffer: global.ArrayBuffer +}); + +module.exports = Window; diff --git a/node_modules/jsdom/lib/jsdom/browser/documentAdapter.js b/node_modules/jsdom/lib/jsdom/browser/documentAdapter.js new file mode 100644 index 0000000..7d66168 --- /dev/null +++ b/node_modules/jsdom/lib/jsdom/browser/documentAdapter.js @@ -0,0 +1,62 @@ +//Tree traversing +exports.getFirstChild = function (node) { + return node.childNodes[0]; +}; + +exports.getChildNodes = function (node) { + return node.childNodes; +}; + +exports.getParentNode = function (node) { + return node.parentNode; +}; + +exports.getAttrList = function (node) { + return node.attributes; +}; + +//Node data +exports.getTagName = function (element) { + return element.tagName.toLowerCase(); +}; + +exports.getNamespaceURI = function (element) { + return element.namespaceURI || 'http://www.w3.org/1999/xhtml'; +}; + +exports.getTextNodeContent = function (textNode) { + return textNode.nodeValue; +}; + +exports.getCommentNodeContent = function (commentNode) { + return commentNode.nodeValue; +}; + +exports.getDocumentTypeNodeName = function (doctypeNode) { + return doctypeNode.name; +}; + +exports.getDocumentTypeNodePublicId = function (doctypeNode) { + return doctypeNode.publicId || null; +}; + +exports.getDocumentTypeNodeSystemId = function (doctypeNode) { + return doctypeNode.systemId || null; +}; + +//Node types +exports.isTextNode = function (node) { + return node.nodeName === '#text'; +}; + +exports.isCommentNode = function (node) { + return node.nodeName === '#comment'; +}; + +exports.isDocumentTypeNode = function (node) { + return node.nodeType === 10; +}; + +exports.isElementNode = function (node) { + return !!node.tagName; +}; diff --git a/node_modules/jsdom/lib/jsdom/browser/documentfeatures.js b/node_modules/jsdom/lib/jsdom/browser/documentfeatures.js new file mode 100644 index 0000000..2e562cb --- /dev/null +++ b/node_modules/jsdom/lib/jsdom/browser/documentfeatures.js @@ -0,0 +1,52 @@ +exports.availableDocumentFeatures = [ + 'FetchExternalResources', + 'ProcessExternalResources', + 'MutationEvents', + 'SkipExternalResources' +]; + +exports.defaultDocumentFeatures = { + "FetchExternalResources": ['script', 'link'/*, 'img', 'css', 'frame'*/], + "ProcessExternalResources": ['script'/*, 'frame', 'iframe'*/], + "MutationEvents": '2.0', + "SkipExternalResources": false +}; + +exports.applyDocumentFeatures = function(doc, features) { + var i, maxFeatures = exports.availableDocumentFeatures.length, + defaultFeatures = exports.defaultDocumentFeatures, + j, + k, + featureName, + featureSource; + + features = features || {}; + + for (i=0; i= this.length) { + return; + } + + this._index = newIndex; + + var state = this._states[newIndex]; + + this._applyState(state); + this._signalPopstate(state); + }, + + pushState: function (data, title, url) { + var state = new StateEntry(data, title, url); + if (this._index + 1 !== this._states.length) { + this._states = this._states.slice(0, this._index + 1); + } + this._states.push(state); + this._applyState(state); + this._index++; + }, + + replaceState: function (data, title, url) { + var state = new StateEntry(data, title, url); + this._states[this._index] = state; + this._applyState(state); + }, + + _applyState: function (state) { + this._location._url = URL.parse(resolveHref(this._location._url.href, state.url)); + }, + + _signalPopstate: function(state) { + if (this._window.document) { + var ev = this._window.document.createEvent("HTMLEvents"); + ev.initEvent("popstate", false, false); + ev.state = state.data; + process.nextTick(function () { + this._window.dispatchEvent(ev); + }.bind(this)); + } + }, + + toString: function () { + return "[object History]"; + } +}; diff --git a/node_modules/jsdom/lib/jsdom/browser/htmltodom.js b/node_modules/jsdom/lib/jsdom/browser/htmltodom.js new file mode 100644 index 0000000..88908dc --- /dev/null +++ b/node_modules/jsdom/lib/jsdom/browser/htmltodom.js @@ -0,0 +1,231 @@ +var parse5 = require('parse5'); +var htmlparser2 = require('htmlparser2'); + +function HtmlToDom(parser, parsingMode) { + if (!parser) { + if (parsingMode === "xml") { + parser = htmlparser2; + } else { + parser = parse5; + } + } + + if (parser.DefaultHandler || (parser.Parser && parser.TreeAdapters)) { + + // Forgiving HTML parser + + if (parser.DefaultHandler){ + // fb55/htmlparser2 + + parser.ParseHtml = function(rawHtml) { + var handler = new parser.DefaultHandler(); + // Check if document is XML + var isXML = parsingMode === "xml"; + var parserInstance = new parser.Parser(handler, { + xmlMode: isXML, + lowerCaseTags: !isXML, + lowerCaseAttributeNames: !isXML, + decodeEntities: true + }); + + parserInstance.includeLocation = false; + parserInstance.parseComplete(rawHtml); + return handler.dom; + }; + } else if (parser.Parser && parser.TreeAdapters) { + parser.ParseHtml = function (rawHtml) { + if (parsingMode === 'xml') { + throw new Error('Can\'t parse XML with parse5, please use htmlparser2 instead.'); + } + var instance = new parser.Parser(parser.TreeAdapters.htmlparser2); + var dom = instance.parse(rawHtml); + return dom.children; + }; + } + + this.appendHtmlToElement = function(html, element) { + + if (typeof html !== 'string') { + html +=''; + } + + var parsed = parser.ParseHtml(html); + + for (var i = 0; i < parsed.length; i++) { + setChild(element, parsed[i]); + } + + return element; + }; + this.appendHtmlToDocument = this.appendHtmlToElement; + + if (parser.Parser && parser.TreeAdapters) { + this.appendHtmlToElement = function (html, element) { + + if (typeof html !== 'string') { + html += ''; + } + + var instance = new parser.Parser(parser.TreeAdapters.htmlparser2); + var parentElement = parser.TreeAdapters.htmlparser2.createElement(element.tagName.toLowerCase(), element.namespaceURI, []); + var dom = instance.parseFragment(html, parentElement); + var parsed = dom.children; + + for (var i = 0; i < parsed.length; i++) { + setChild(element, parsed[i]); + } + + return element; + }; + } + + } else if (parser.moduleName == 'HTML5') { /* HTML5 parser */ + this.appendHtmlToElement = function(html, element) { + + if (typeof html !== 'string') { + html += ''; + } + if (html.length > 0) { + if (element.nodeType == 9) { + new parser.Parser({document: element}).parse(html); + } + else { + var p = new parser.Parser({document: element.ownerDocument}); + p.parse_fragment(html, element); + } + } + }; + } else { + this.appendHtmlToElement = function () { + console.log(''); + console.log('###########################################################'); + console.log('# WARNING: No compatible HTML parser was given.'); + console.log('# Element.innerHTML setter support has been disabled'); + console.log('# Element.innerHTML getter support will still function'); + console.log('###########################################################'); + console.log(''); + }; + } +}; + +// utility function for forgiving parser +function setChild(parent, node) { + + var c, newNode, currentDocument = parent._ownerDocument || parent; + + switch (node.type) + { + case 'tag': + case 'script': + case 'style': + try { + newNode = currentDocument._createElementNoTagNameValidation(node.name); + newNode._namespaceURI = node.namespace || "http://www.w3.org/1999/xhtml"; + if (node.location) { + newNode.sourceLocation = node.location; + newNode.sourceLocation.file = parent.sourceLocation.file; + } + } catch (err) { + currentDocument.raise('error', 'invalid markup', { + exception: err, + node : node + }); + + return null; + } + break; + + case 'root': + // If we are in