Socket
Socket
Sign inDemoInstall

jsdom

Package Overview
Dependencies
Maintainers
6
Versions
263
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsdom - npm Package Compare versions

Comparing version 24.1.1 to 24.1.2

385

lib/jsdom/browser/Window.js

@@ -94,20 +94,30 @@ "use strict";

exports.createWindow = function (options) {
return new Window(options);
};
const jsGlobalEntriesToInstall = Object.entries(jsGlobals).filter(([name]) => name in global);
// https://html.spec.whatwg.org/#the-window-object
function setupWindow(windowInstance, { runScripts }) {
if (runScripts === "outside-only" || runScripts === "dangerously") {
contextifyWindow(windowInstance);
exports.createWindow = options => {
const makeVMContext = options.runScripts === "outside-only" || options.runScripts === "dangerously";
// Bootstrap with an empty object from the Node.js realm. We'll muck with its prototype chain shortly.
const window = {};
// Make window into a global object: either via vm, or just aliasing the Node.js globals.
// Also set _globalObject and _globalProxy.
//
// TODO: don't expose _globalObject and _globalProxy as public properties. While you're there, audit usage sites to
// see how necessary they really are.
if (makeVMContext) {
vm.createContext(window);
window._globalObject = window;
window._globalProxy = vm.runInContext("this", window);
// Without this, these globals will only appear to scripts running inside the context using vm.runScript; they will
// not appear to scripts running from the outside, including to JSDOM implementation code.
for (const [globalName, globalPropDesc] of jsGlobalEntriesToInstall) {
const propDesc = { ...globalPropDesc, value: vm.runInContext(globalName, windowInstance) };
Object.defineProperty(windowInstance, globalName, propDesc);
const propDesc = { ...globalPropDesc, value: vm.runInContext(globalName, window) };
Object.defineProperty(window, globalName, propDesc);
}
} else {
window._globalObject = window._globalProxy = window;
// Without contextifying the window, none of the globals will exist. So, let's at least alias them from the Node.js

@@ -117,26 +127,37 @@ // context. See https://github.com/jsdom/jsdom/issues/2727 for more background and discussion.

const propDesc = { ...globalPropDesc, value: global[globalName] };
Object.defineProperty(windowInstance, globalName, propDesc);
Object.defineProperty(window, globalName, propDesc);
}
}
installInterfaces(windowInstance, ["Window"]);
// Create instances of all the web platform interfaces and install them on the window.
installInterfaces(window, ["Window"]);
const EventTargetConstructor = windowInstance.EventTarget;
// Now we have an EventTarget contructor so we can work on the prototype chain.
// eslint-disable-next-line func-name-matching, func-style, no-shadow
const windowConstructor = function Window() {
// eslint-disable-next-line func-name-matching, func-style
const WindowConstructor = function Window() {
throw new TypeError("Illegal constructor");
};
Object.setPrototypeOf(windowConstructor, EventTargetConstructor);
Object.setPrototypeOf(WindowConstructor, window.EventTarget);
Object.defineProperty(windowInstance, "Window", {
Object.defineProperty(window, "Window", {
configurable: true,
writable: true,
value: windowConstructor
value: WindowConstructor
});
const windowPrototype = Object.create(EventTargetConstructor.prototype);
// TODO: do an actual WindowProperties object. See https://github.com/jsdom/jsdom/pull/3765 for an attempt.
const windowPropertiesObject = Object.create(window.EventTarget.prototype);
Object.defineProperties(windowPropertiesObject, {
[Symbol.toStringTag]: {
value: "WindowProperties",
configurable: true
}
});
namedPropertiesWindow.initializeWindow(window, window._globalProxy);
const windowPrototype = Object.create(windowPropertiesObject);
Object.defineProperties(windowPrototype, {
constructor: {
value: windowConstructor,
value: WindowConstructor,
writable: true,

@@ -151,15 +172,58 @@ configurable: true

windowConstructor.prototype = windowPrototype;
Object.setPrototypeOf(windowInstance, windowPrototype);
WindowConstructor.prototype = windowPrototype;
Object.setPrototypeOf(window, windowPrototype);
if (makeVMContext) {
Object.setPrototypeOf(window._globalProxy, windowPrototype);
EventTarget.setup(windowInstance, windowInstance);
mixin(windowInstance, WindowEventHandlersImpl.prototype);
mixin(windowInstance, GlobalEventHandlersImpl.prototype);
windowInstance._initGlobalEvents();
// TODO next major version: include this.
// Object.setPrototypeOf(window.EventTarget.prototype, window.Object.prototype);
}
Object.defineProperty(windowInstance, "onbeforeunload", {
// Now that the prototype chain is fully set up, call the superclass setup.
EventTarget.setup(window, window);
installEventHandlers(window);
installOwnProperties(window, options);
// Not sure why this is necessary... TODO figure it out.
Object.defineProperty(idlUtils.implForWrapper(window), idlUtils.wrapperSymbol, { get: () => window._globalProxy });
// Fire or prepare to fire load and pageshow events.
process.nextTick(() => {
if (!window.document) {
return; // window might've been closed already
}
if (window.document.readyState === "complete") {
fireAnEvent("load", window, undefined, {}, true);
} else {
window.document.addEventListener("load", () => {
fireAnEvent("load", window, undefined, {}, true);
if (!window._document) {
return; // window might've been closed already
}
const documentImpl = idlUtils.implForWrapper(window._document);
if (!documentImpl._pageShowingFlag) {
documentImpl._pageShowingFlag = true;
fireAPageTransitionEvent("pageshow", window, false);
}
});
}
});
return window;
};
function installEventHandlers(window) {
mixin(window, WindowEventHandlersImpl.prototype);
mixin(window, GlobalEventHandlersImpl.prototype);
window._initGlobalEvents();
Object.defineProperty(window, "onbeforeunload", {
configurable: true,
enumerable: true,
get() {
return idlUtils.tryWrapperForImpl(getCurrentEventHandlerValue(this, "beforeunload"));
return idlUtils.tryWrapperForImpl(getCurrentEventHandlerValue(window, "beforeunload"));
},

@@ -170,15 +234,15 @@ set(V) {

} else {
V = OnBeforeUnloadEventHandlerNonNull.convert(windowInstance, V, {
V = OnBeforeUnloadEventHandlerNonNull.convert(window, V, {
context: "Failed to set the 'onbeforeunload' property on 'Window': The provided value"
});
}
this._setEventHandlerFor("beforeunload", V);
window._setEventHandlerFor("beforeunload", V);
}
});
Object.defineProperty(windowInstance, "onerror", {
Object.defineProperty(window, "onerror", {
configurable: true,
enumerable: true,
get() {
return idlUtils.tryWrapperForImpl(getCurrentEventHandlerValue(this, "error"));
return idlUtils.tryWrapperForImpl(getCurrentEventHandlerValue(window, "error"));
},

@@ -189,7 +253,7 @@ set(V) {

} else {
V = OnErrorEventHandlerNonNull.convert(windowInstance, V, {
V = OnErrorEventHandlerNonNull.convert(window, V, {
context: "Failed to set the 'onerror' property on 'Window': The provided value"
});
}
this._setEventHandlerFor("error", V);
window._setEventHandlerFor("error", V);
}

@@ -199,7 +263,7 @@ });

for (const event of events) {
Object.defineProperty(windowInstance, `on${event}`, {
Object.defineProperty(window, `on${event}`, {
configurable: true,
enumerable: true,
get() {
return idlUtils.tryWrapperForImpl(getCurrentEventHandlerValue(this, event));
return idlUtils.tryWrapperForImpl(getCurrentEventHandlerValue(window, event));
},

@@ -210,50 +274,21 @@ set(V) {

} else {
V = EventHandlerNonNull.convert(windowInstance, V, {
V = EventHandlerNonNull.convert(window, V, {
context: `Failed to set the 'on${event}' property on 'Window': The provided value`
});
}
this._setEventHandlerFor(event, V);
window._setEventHandlerFor(event, V);
}
});
}
windowInstance._globalObject = windowInstance;
}
function makeReplaceablePropertyDescriptor(property, window) {
const desc = {
set(value) {
Object.defineProperty(window, property, {
configurable: true,
enumerable: true,
writable: true,
value
});
}
};
Object.defineProperty(desc.set, "name", { value: `set ${property}` });
return desc;
}
// NOTE: per https://heycam.github.io/webidl/#Global, all properties on the Window object must be own-properties.
// That is why we assign everything inside of the constructor, instead of using a shared prototype.
// You can verify this in e.g. Firefox or Internet Explorer, which do a good job with Web IDL compliance.
function Window(options) {
setupWindow(this, { runScripts: options.runScripts });
function installOwnProperties(window, options) {
const windowInitialized = performance.now();
const window = this;
// ### PRIVATE DATA PROPERTIES
this._resourceLoader = options.resourceLoader;
window._resourceLoader = options.resourceLoader;
// vm initialization is deferred until script processing is activated
this._globalProxy = this;
Object.defineProperty(idlUtils.implForWrapper(this), idlUtils.wrapperSymbol, { get: () => this._globalProxy });
// List options explicitly to be clear which are passed through
this._document = documents.createWrapper(window, {
window._document = documents.createWrapper(window, {
parsingMode: options.parsingMode,

@@ -267,30 +302,25 @@ contentType: options.contentType,

parseOptions: options.parseOptions,
defaultView: this._globalProxy,
global: this,
defaultView: window._globalProxy,
global: window,
parentOrigin: options.parentOrigin
}, { alwaysUseDocumentClass: true });
if (vm.isContext(window)) {
const documentImpl = idlUtils.implForWrapper(window._document);
documentImpl._defaultView = window._globalProxy = vm.runInContext("this", window);
}
const documentOrigin = idlUtils.implForWrapper(window._document)._origin;
window._origin = documentOrigin;
const documentOrigin = idlUtils.implForWrapper(this._document)._origin;
this._origin = documentOrigin;
// https://html.spec.whatwg.org/#session-history
this._sessionHistory = new SessionHistory({
document: idlUtils.implForWrapper(this._document),
url: idlUtils.implForWrapper(this._document)._URL,
window._sessionHistory = new SessionHistory({
document: idlUtils.implForWrapper(window._document),
url: idlUtils.implForWrapper(window._document)._URL,
stateObject: null
}, this);
}, window);
this._virtualConsole = options.virtualConsole;
window._virtualConsole = options.virtualConsole;
this._runScripts = options.runScripts;
window._runScripts = options.runScripts;
// Set up the window as if it's a top level window.
// If it's not, then references will be corrected by frame/iframe code.
this._parent = this._top = this._globalProxy;
this._frameElement = null;
window._parent = window._top = window._globalProxy;
window._frameElement = null;

@@ -300,9 +330,9 @@ // This implements window.frames.length, since window.frames returns a

// HTMLFrameElement implementation.
this._length = 0;
window._length = 0;
// https://dom.spec.whatwg.org/#window-current-event
this._currentEvent = undefined;
window._currentEvent = undefined;
this._pretendToBeVisual = options.pretendToBeVisual;
this._storageQuota = options.storageQuota;
window._pretendToBeVisual = options.pretendToBeVisual;
window._storageQuota = options.storageQuota;

@@ -313,9 +343,9 @@ // Some properties (such as localStorage and sessionStorage) share data

if (options.commonForOrigin && options.commonForOrigin[documentOrigin]) {
this._commonForOrigin = options.commonForOrigin;
window._commonForOrigin = options.commonForOrigin;
} else {
this._commonForOrigin = {
window._commonForOrigin = {
[documentOrigin]: {
localStorageArea: new Map(),
sessionStorageArea: new Map(),
windowsInSameOrigin: [this]
windowsInSameOrigin: [window]
}

@@ -325,19 +355,19 @@ };

this._currentOriginData = this._commonForOrigin[documentOrigin];
window._currentOriginData = window._commonForOrigin[documentOrigin];
// ### WEB STORAGE
this._localStorage = Storage.create(window, [], {
associatedWindow: this,
storageArea: this._currentOriginData.localStorageArea,
window._localStorage = Storage.create(window, [], {
associatedWindow: window,
storageArea: window._currentOriginData.localStorageArea,
type: "localStorage",
url: this._document.documentURI,
storageQuota: this._storageQuota
url: window._document.documentURI,
storageQuota: window._storageQuota
});
this._sessionStorage = Storage.create(window, [], {
associatedWindow: this,
storageArea: this._currentOriginData.sessionStorageArea,
window._sessionStorage = Storage.create(window, [], {
associatedWindow: window,
storageArea: window._currentOriginData.sessionStorageArea,
type: "sessionStorage",
url: this._document.documentURI,
storageQuota: this._storageQuota
url: window._document.documentURI,
storageQuota: window._storageQuota
});

@@ -348,6 +378,6 @@

// https://w3c.github.io/selection-api/#dfn-selection
this._selection = Selection.createImpl(window);
window._selection = Selection.createImpl(window);
// https://w3c.github.io/selection-api/#dom-window
this.getSelection = function () {
window.getSelection = function () {
return window._selection;

@@ -365,3 +395,3 @@ };

const external = External.create(window);
const navigator = Navigator.create(window, [], { userAgent: this._resourceLoader._userAgent });
const navigator = Navigator.create(window, [], { userAgent: window._resourceLoader._userAgent });
const performanceImpl = Performance.create(window, [], {

@@ -373,5 +403,5 @@ timeOrigin: performance.timeOrigin + windowInitialized,

const crypto = Crypto.create(window);
this._customElementRegistry = CustomElementRegistry.create(window);
window._customElementRegistry = CustomElementRegistry.create(window);
define(this, {
define(window, {
get length() {

@@ -448,3 +478,3 @@ return window._length;

get localStorage() {
if (idlUtils.implForWrapper(this._document)._origin === "null") {
if (idlUtils.implForWrapper(window._document)._origin === "null") {
throw DOMException.create(window, [

@@ -456,6 +486,6 @@ "localStorage is not available for opaque origins",

return this._localStorage;
return window._localStorage;
},
get sessionStorage() {
if (idlUtils.implForWrapper(this._document)._origin === "null") {
if (idlUtils.implForWrapper(window._document)._origin === "null") {
throw DOMException.create(window, [

@@ -467,6 +497,6 @@ "sessionStorage is not available for opaque origins",

return this._sessionStorage;
return window._sessionStorage;
},
get customElements() {
return this._customElementRegistry;
return window._customElementRegistry;
},

@@ -478,3 +508,3 @@ get event() {

Object.defineProperties(this, {
Object.defineProperties(window, {
// [Replaceable]:

@@ -504,4 +534,2 @@ self: makeReplaceablePropertyDescriptor("self", window),

namedPropertiesWindow.initializeWindow(this, this._globalProxy);
// ### METHODS

@@ -516,3 +544,3 @@

this.setTimeout = function (handler, timeout = 0, ...args) {
window.setTimeout = function (handler, timeout = 0, ...args) {
if (typeof handler !== "function") {

@@ -525,3 +553,3 @@ handler = webIDLConversions.DOMString(handler);

};
this.setInterval = function (handler, timeout = 0, ...args) {
window.setInterval = function (handler, timeout = 0, ...args) {
if (typeof handler !== "function") {

@@ -535,3 +563,3 @@ handler = webIDLConversions.DOMString(handler);

this.clearTimeout = function (handle = 0) {
window.clearTimeout = function (handle = 0) {
handle = webIDLConversions.long(handle);

@@ -545,3 +573,3 @@

};
this.clearInterval = function (handle = 0) {
window.clearInterval = function (handle = 0) {
handle = webIDLConversions.long(handle);

@@ -551,3 +579,3 @@

if (nodejsTimer) {
// We use setTimeout() in timerInitializationSteps even for this.setInterval().
// We use setTimeout() in timerInitializationSteps even for window.setInterval().
clearTimeout(nodejsTimer);

@@ -605,4 +633,4 @@ listOfActiveTimers.delete(handle);

this.queueMicrotask = function (callback) {
callback = IDLFunction.convert(this, callback);
window.queueMicrotask = function (callback) {
callback = IDLFunction.convert(window, callback);

@@ -628,5 +656,5 @@ queueMicrotask(() => {

if (this._pretendToBeVisual) {
this.requestAnimationFrame = function (callback) {
callback = IDLFunction.convert(this, callback);
if (window._pretendToBeVisual) {
window.requestAnimationFrame = function (callback) {
callback = IDLFunction.convert(window, callback);

@@ -646,3 +674,3 @@ const handle = ++animationFrameCallbackId;

this.cancelAnimationFrame = function (handle) {
window.cancelAnimationFrame = function (handle) {
handle = webIDLConversions["unsigned long"](handle);

@@ -721,3 +749,3 @@

Object.defineProperty(Option, "prototype", {
value: this.HTMLOptionElement.prototype,
value: window.HTMLOptionElement.prototype,
configurable: false,

@@ -748,3 +776,3 @@ enumerable: false,

Object.defineProperty(Image, "prototype", {
value: this.HTMLImageElement.prototype,
value: window.HTMLImageElement.prototype,
configurable: false,

@@ -773,3 +801,3 @@ enumerable: false,

Object.defineProperty(Audio, "prototype", {
value: this.HTMLAudioElement.prototype,
value: window.HTMLAudioElement.prototype,
configurable: false,

@@ -786,5 +814,5 @@ enumerable: false,

this.postMessage = postMessage(window);
window.postMessage = postMessage(window);
this.atob = function (str) {
window.atob = function (str) {
try {

@@ -801,3 +829,3 @@ return atob(str);

this.btoa = function (str) {
window.btoa = function (str) {
try {

@@ -814,4 +842,4 @@ return btoa(str);

this.stop = function () {
const manager = idlUtils.implForWrapper(this._document)._requestManager;
window.stop = function () {
const manager = idlUtils.implForWrapper(window._document)._requestManager;
if (manager) {

@@ -822,35 +850,35 @@ manager.close();

this.close = function () {
window.close = function () {
// Recursively close child frame windows, then ourselves (depth-first).
for (let i = 0; i < this.length; ++i) {
this[i].close();
for (let i = 0; i < window.length; ++i) {
window[i].close();
}
// Clear out all listeners. Any in-flight or upcoming events should not get delivered.
idlUtils.implForWrapper(this)._eventListeners = Object.create(null);
idlUtils.implForWrapper(window)._eventListeners = Object.create(null);
if (this._document) {
if (this._document.body) {
this._document.body.innerHTML = "";
if (window._document) {
if (window._document.body) {
window._document.body.innerHTML = "";
}
if (this._document.close) {
if (window._document.close) {
// It's especially important to clear out the listeners here because document.close() causes a "load" event to
// fire.
idlUtils.implForWrapper(this._document)._eventListeners = Object.create(null);
this._document.close();
idlUtils.implForWrapper(window._document)._eventListeners = Object.create(null);
window._document.close();
}
const doc = idlUtils.implForWrapper(this._document);
const doc = idlUtils.implForWrapper(window._document);
if (doc._requestManager) {
doc._requestManager.close();
}
delete this._document;
delete window._document;
}
stopAllTimers();
WebSocketImpl.cleanUpWindow(this);
WebSocketImpl.cleanUpWindow(window);
};
this.getComputedStyle = function (elt, pseudoElt = undefined) {
elt = Element.convert(this, elt);
window.getComputedStyle = function (elt, pseudoElt = undefined) {
elt = Element.convert(window, elt);
if (pseudoElt !== undefined && pseudoElt !== null) {

@@ -867,3 +895,3 @@ pseudoElt = webIDLConversions.DOMString(pseudoElt);

notImplemented("window.getComputedStyle(elt, pseudoElt)", this);
notImplemented("window.getComputedStyle(elt, pseudoElt)", window);
}

@@ -892,3 +920,3 @@

this.getSelection = function () {
window.getSelection = function () {
return window._document.getSelection();

@@ -898,5 +926,5 @@ };

// The captureEvents() and releaseEvents() methods must do nothing
this.captureEvents = function () {};
window.captureEvents = function () {};
this.releaseEvents = function () {};
window.releaseEvents = function () {};

@@ -911,3 +939,3 @@ // ### PUBLIC DATA PROPERTIES (TODO: should be getters)

this.console = {
window.console = {
assert: wrapConsoleMethod("assert"),

@@ -940,3 +968,3 @@ clear: wrapConsoleMethod("clear"),

define(this, {
define(window, {
name: "",

@@ -973,35 +1001,18 @@ status: "",

});
}
// ### INITIALIZATION
process.nextTick(() => {
if (!window.document) {
return; // window might've been closed already
}
if (window.document.readyState === "complete") {
fireAnEvent("load", window, undefined, {}, true);
} else {
window.document.addEventListener("load", () => {
fireAnEvent("load", window, undefined, {}, true);
if (!window._document) {
return; // window might've been closed already
}
const documentImpl = idlUtils.implForWrapper(window._document);
if (!documentImpl._pageShowingFlag) {
documentImpl._pageShowingFlag = true;
fireAPageTransitionEvent("pageshow", window, false);
}
function makeReplaceablePropertyDescriptor(property, window) {
const desc = {
set(value) {
Object.defineProperty(window, property, {
configurable: true,
enumerable: true,
writable: true,
value
});
}
});
}
};
function contextifyWindow(window) {
if (vm.isContext(window)) {
return;
}
vm.createContext(window);
Object.defineProperty(desc.set, "name", { value: `set ${property}` });
return desc;
}

@@ -79,6 +79,4 @@ "use strict";

this._ownerDocument._lastFocusedElement = null;
focusing.fireFocusEventWithTargetAdjustment("blur", this, this._ownerDocument);
focusing.fireFocusEventWithTargetAdjustment("focusout", this, this._ownerDocument, { bubbles: true });
focusing.fireFocusEventWithTargetAdjustment("focus", this._ownerDocument, this);
focusing.fireFocusEventWithTargetAdjustment("focusin", this._ownerDocument, this, { bubbles: true });
focusing.fireFocusEventWithTargetAdjustment("blur", this, null);
focusing.fireFocusEventWithTargetAdjustment("focusout", this, null, { bubbles: true });
this._ownerDocument.getSelection().empty();

@@ -85,0 +83,0 @@ }

{
"name": "jsdom",
"version": "24.1.1",
"version": "24.1.2",
"description": "A JavaScript implementation of many web standards",

@@ -21,3 +21,6 @@ "keywords": [

"license": "MIT",
"repository": "jsdom/jsdom",
"repository": {
"type": "git",
"url": "git+https://github.com/jsdom/jsdom.git"
},
"dependencies": {

@@ -24,0 +27,0 @@ "cssstyle": "^4.0.1",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc