jsdom
Advanced tools
Comparing version 21.0.0 to 21.1.0
@@ -34,3 +34,3 @@ "use strict"; | ||
const SessionHistory = require("../living/window/SessionHistory"); | ||
const { forEachMatchingSheetRuleOfElement, getResolvedValue, propertiesWithResolvedValueImplemented, | ||
const { getDeclarationForElement, getResolvedValue, propertiesWithResolvedValueImplemented, | ||
SHADOW_DOM_PSEUDO_REGEXP } = require("../living/helpers/style-rules.js"); | ||
@@ -838,12 +838,10 @@ const CustomElementRegistry = require("../living/generated/CustomElementRegistry"); | ||
const { forEach } = Array.prototype; | ||
const { style } = elt; | ||
forEachMatchingSheetRuleOfElement(elt, rule => { | ||
forEach.call(rule.style, property => { | ||
declaration.setProperty( | ||
property, | ||
rule.style.getPropertyValue(property), | ||
rule.style.getPropertyPriority(property) | ||
); | ||
}); | ||
const elementDeclaration = getDeclarationForElement(elt); | ||
forEach.call(elementDeclaration, property => { | ||
declaration.setProperty( | ||
property, | ||
elementDeclaration.getPropertyValue(property), | ||
elementDeclaration.getPropertyPriority(property) | ||
); | ||
}); | ||
@@ -857,6 +855,2 @@ | ||
forEach.call(style, property => { | ||
declaration.setProperty(property, style.getPropertyValue(property), style.getPropertyPriority(property)); | ||
}); | ||
return declaration; | ||
@@ -863,0 +857,0 @@ }; |
@@ -8,4 +8,38 @@ "use strict"; | ||
const MouseEventInit = require("../generated/MouseEventInit"); | ||
const { wrapperForImpl } = require("../generated/utils"); | ||
class MouseEventImpl extends UIEventImpl { | ||
get x() { | ||
return this.clientX; | ||
} | ||
get y() { | ||
return this.clientY; | ||
} | ||
get pageX() { | ||
if (this._dispatchFlag) { | ||
return 0; | ||
} | ||
const offset = wrapperForImpl(this.view)?.scrollX || 0; | ||
return offset + this.clientX; | ||
} | ||
get pageY() { | ||
if (this._dispatchFlag) { | ||
return 0; | ||
} | ||
const offset = wrapperForImpl(this.view)?.scrollY || 0; | ||
return offset + this.clientY; | ||
} | ||
get offsetX() { | ||
if (this._dispatchFlag) { | ||
return 0; | ||
} | ||
return this.pageX; | ||
} | ||
get offsetY() { | ||
if (this._dispatchFlag) { | ||
return 0; | ||
} | ||
return this.pageY; | ||
} | ||
initMouseEvent( | ||
@@ -12,0 +46,0 @@ type, |
@@ -473,2 +473,66 @@ "use strict"; | ||
} | ||
get pageX() { | ||
const esValue = this !== null && this !== undefined ? this : globalObject; | ||
if (!exports.is(esValue)) { | ||
throw new globalObject.TypeError("'get pageX' called on an object that is not a valid instance of MouseEvent."); | ||
} | ||
return esValue[implSymbol]["pageX"]; | ||
} | ||
get pageY() { | ||
const esValue = this !== null && this !== undefined ? this : globalObject; | ||
if (!exports.is(esValue)) { | ||
throw new globalObject.TypeError("'get pageY' called on an object that is not a valid instance of MouseEvent."); | ||
} | ||
return esValue[implSymbol]["pageY"]; | ||
} | ||
get x() { | ||
const esValue = this !== null && this !== undefined ? this : globalObject; | ||
if (!exports.is(esValue)) { | ||
throw new globalObject.TypeError("'get x' called on an object that is not a valid instance of MouseEvent."); | ||
} | ||
return esValue[implSymbol]["x"]; | ||
} | ||
get y() { | ||
const esValue = this !== null && this !== undefined ? this : globalObject; | ||
if (!exports.is(esValue)) { | ||
throw new globalObject.TypeError("'get y' called on an object that is not a valid instance of MouseEvent."); | ||
} | ||
return esValue[implSymbol]["y"]; | ||
} | ||
get offsetX() { | ||
const esValue = this !== null && this !== undefined ? this : globalObject; | ||
if (!exports.is(esValue)) { | ||
throw new globalObject.TypeError( | ||
"'get offsetX' called on an object that is not a valid instance of MouseEvent." | ||
); | ||
} | ||
return esValue[implSymbol]["offsetX"]; | ||
} | ||
get offsetY() { | ||
const esValue = this !== null && this !== undefined ? this : globalObject; | ||
if (!exports.is(esValue)) { | ||
throw new globalObject.TypeError( | ||
"'get offsetY' called on an object that is not a valid instance of MouseEvent." | ||
); | ||
} | ||
return esValue[implSymbol]["offsetY"]; | ||
} | ||
} | ||
@@ -489,2 +553,8 @@ Object.defineProperties(MouseEvent.prototype, { | ||
relatedTarget: { enumerable: true }, | ||
pageX: { enumerable: true }, | ||
pageY: { enumerable: true }, | ||
x: { enumerable: true }, | ||
y: { enumerable: true }, | ||
offsetX: { enumerable: true }, | ||
offsetY: { enumerable: true }, | ||
[Symbol.toStringTag]: { value: "MouseEvent", configurable: true } | ||
@@ -491,0 +561,0 @@ }); |
@@ -52,2 +52,14 @@ "use strict"; | ||
{ | ||
const key = "clientX"; | ||
let value = obj === undefined || obj === null ? undefined : obj[key]; | ||
if (value !== undefined) { | ||
value = conversions["double"](value, { context: context + " has member 'clientX' that", globals: globalObject }); | ||
ret[key] = value; | ||
} else { | ||
ret[key] = 0.0; | ||
} | ||
} | ||
{ | ||
const key = "clientY"; | ||
@@ -65,2 +77,14 @@ let value = obj === undefined || obj === null ? undefined : obj[key]; | ||
{ | ||
const key = "clientY"; | ||
let value = obj === undefined || obj === null ? undefined : obj[key]; | ||
if (value !== undefined) { | ||
value = conversions["double"](value, { context: context + " has member 'clientY' that", globals: globalObject }); | ||
ret[key] = value; | ||
} else { | ||
ret[key] = 0.0; | ||
} | ||
} | ||
{ | ||
const key = "relatedTarget"; | ||
@@ -93,2 +117,14 @@ let value = obj === undefined || obj === null ? undefined : obj[key]; | ||
{ | ||
const key = "screenX"; | ||
let value = obj === undefined || obj === null ? undefined : obj[key]; | ||
if (value !== undefined) { | ||
value = conversions["double"](value, { context: context + " has member 'screenX' that", globals: globalObject }); | ||
ret[key] = value; | ||
} else { | ||
ret[key] = 0.0; | ||
} | ||
} | ||
{ | ||
const key = "screenY"; | ||
@@ -104,2 +140,14 @@ let value = obj === undefined || obj === null ? undefined : obj[key]; | ||
} | ||
{ | ||
const key = "screenY"; | ||
let value = obj === undefined || obj === null ? undefined : obj[key]; | ||
if (value !== undefined) { | ||
value = conversions["double"](value, { context: context + " has member 'screenY' that", globals: globalObject }); | ||
ret[key] = value; | ||
} else { | ||
ret[key] = 0.0; | ||
} | ||
} | ||
}; | ||
@@ -106,0 +154,0 @@ |
"use strict"; | ||
const cssom = require("cssom"); | ||
const { CSSStyleDeclaration } = require("cssstyle"); | ||
const defaultStyleSheet = require("../../browser/default-stylesheet"); | ||
@@ -14,13 +15,19 @@ const { matchesDontThrow } = require("./selectors"); | ||
exports.propertiesWithResolvedValueImplemented = { | ||
__proto__: null, | ||
"__proto__": null, | ||
// https://drafts.csswg.org/css2/visufx.html#visibility | ||
visibility: { | ||
"visibility": { | ||
inherited: true, | ||
initial: "visible", | ||
computedValue: "as-specified" | ||
}, | ||
// https://svgwg.org/svg2-draft/interact.html#PointerEventsProperty | ||
"pointer-events": { | ||
inherited: true, | ||
initial: "auto", | ||
computedValue: "as-specified" | ||
} | ||
}; | ||
exports.forEachMatchingSheetRuleOfElement = (elementImpl, handleRule) => { | ||
function forEachMatchingSheetRuleOfElement(elementImpl, handleRule) { | ||
function handleSheet(sheet) { | ||
@@ -48,4 +55,52 @@ forEach.call(sheet.cssRules, rule => { | ||
forEach.call(elementImpl._ownerDocument.styleSheets._list, handleSheet); | ||
} | ||
exports.invalidateStyleCache = elementImpl => { | ||
if (elementImpl._attached) { | ||
elementImpl._ownerDocument._styleCache = null; | ||
} | ||
}; | ||
exports.getDeclarationForElement = elementImpl => { | ||
let styleCache = elementImpl._ownerDocument._styleCache; | ||
if (!styleCache) { | ||
styleCache = elementImpl._ownerDocument._styleCache = new WeakMap(); | ||
} | ||
const cachedDeclaration = styleCache.get(elementImpl); | ||
if (cachedDeclaration) { | ||
return cachedDeclaration; | ||
} | ||
const declaration = new CSSStyleDeclaration(); | ||
function handleProperty(style, property) { | ||
const value = style.getPropertyValue(property); | ||
// https://drafts.csswg.org/css-cascade-4/#valdef-all-unset | ||
if (value === "unset") { | ||
declaration.removeProperty(property); | ||
} else { | ||
declaration.setProperty( | ||
property, | ||
value, | ||
style.getPropertyPriority(property) | ||
); | ||
} | ||
} | ||
forEachMatchingSheetRuleOfElement(elementImpl, rule => { | ||
forEach.call(rule.style, property => { | ||
handleProperty(rule.style, property); | ||
}); | ||
}); | ||
forEach.call(elementImpl.style, property => { | ||
handleProperty(elementImpl.style, property); | ||
}); | ||
styleCache.set(elementImpl, declaration); | ||
return declaration; | ||
}; | ||
function matches(rule, element) { | ||
@@ -62,18 +117,3 @@ return matchesDontThrow(element, rule.selectorText); | ||
function getCascadedPropertyValue(element, property) { | ||
let value = ""; | ||
exports.forEachMatchingSheetRuleOfElement(element, rule => { | ||
const propertyValue = rule.style.getPropertyValue(property); | ||
// getPropertyValue returns "" if the property is not found | ||
if (propertyValue !== "") { | ||
value = propertyValue; | ||
} | ||
}); | ||
const inlineValue = element.style.getPropertyValue(property); | ||
if (inlineValue !== "" && inlineValue !== null) { | ||
value = inlineValue; | ||
} | ||
return value; | ||
return exports.getDeclarationForElement(element).getPropertyValue(property); | ||
} | ||
@@ -110,3 +150,3 @@ | ||
// https://drafts.csswg.org/cssom/#resolved-value | ||
// Only implements `visibility` | ||
// Only implements `visibility` and `pointer-events` | ||
exports.getResolvedValue = (element, property) => { | ||
@@ -113,0 +153,0 @@ // Determined for special case properties, none of which are implemented here. |
@@ -5,2 +5,3 @@ "use strict"; | ||
const whatwgURL = require("whatwg-url"); | ||
const { invalidateStyleCache } = require("./style-rules"); | ||
@@ -22,2 +23,4 @@ // TODO: this should really implement https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet | ||
invalidateStyleCache(elementImpl); | ||
// TODO: "Set the CSS style sheet’s parent CSS style sheet, owner node and owner CSS rule to null." | ||
@@ -57,2 +60,4 @@ // Probably when we have a real CSSOM implementation. | ||
invalidateStyleCache(elementImpl); | ||
// TODO: title and disabled stuff | ||
@@ -71,2 +76,7 @@ } | ||
function onStylesheetLoad(data) { | ||
// if the element was detached before the load could finish, don't process the data | ||
if (!elementImpl._attached) { | ||
return; | ||
} | ||
const css = whatwgEncoding.decode(data, defaultEncoding); | ||
@@ -73,0 +83,0 @@ |
@@ -133,2 +133,3 @@ /* eslint-disable global-require */ | ||
PageTransitionEvent: require("./generated/PageTransitionEvent"), | ||
SubmitEvent: require("./generated/SubmitEvent"), | ||
@@ -135,0 +136,0 @@ UIEvent: require("./generated/UIEvent"), |
@@ -198,2 +198,5 @@ "use strict"; | ||
this._throwOnDynamicMarkupInsertionCounter = 0; | ||
// Cache of computed element styles | ||
this._styleCache = null; | ||
} | ||
@@ -200,0 +203,0 @@ |
@@ -12,2 +12,3 @@ "use strict"; | ||
const { parseURLToResultingURLRecord } = require("../helpers/document-base-url"); | ||
const SubmitEvent = require("../generated/SubmitEvent"); | ||
@@ -84,11 +85,7 @@ const encTypes = new Set([ | ||
submit() { | ||
if (!fireAnEvent("submit", this, undefined, { bubbles: true, cancelable: true })) { | ||
return; | ||
} | ||
notImplemented("HTMLFormElement.prototype.submit", this._ownerDocument._defaultView); | ||
} | ||
requestSubmit(submitter = undefined) { | ||
if (submitter !== undefined) { | ||
requestSubmit(submitter = null) { | ||
if (submitter !== null) { | ||
if (!isSubmitButton(submitter)) { | ||
@@ -111,3 +108,3 @@ throw new TypeError("The specified element is not a submit button"); | ||
if (!fireAnEvent("submit", this, undefined, { bubbles: true, cancelable: true })) { | ||
if (!fireAnEvent("submit", this, SubmitEvent, { bubbles: true, cancelable: true, submitter })) { | ||
return; | ||
@@ -114,0 +111,0 @@ } |
@@ -5,3 +5,3 @@ "use strict"; | ||
const idlUtils = require("../generated/utils"); | ||
const { fetchStylesheet } = require("../helpers/stylesheets"); | ||
const { fetchStylesheet, removeStylesheet } = require("../helpers/stylesheets"); | ||
const { parseURLToResultingURLRecord } = require("../helpers/document-base-url"); | ||
@@ -36,2 +36,9 @@ const whatwgURL = require("whatwg-url"); | ||
_detach() { | ||
super._detach(); | ||
if (this.sheet) { | ||
removeStylesheet(this.sheet, this); | ||
} | ||
} | ||
_attrModified(name, value, oldValue) { | ||
@@ -38,0 +45,0 @@ super._attrModified(name, value, oldValue); |
@@ -12,3 +12,2 @@ "use strict"; | ||
const { childTextContent } = require("../helpers/text"); | ||
const { fireAnEvent } = require("../helpers/events"); | ||
const { parseURLToResultingURLRecord } = require("../helpers/document-base-url"); | ||
@@ -117,4 +116,2 @@ const nodeTypes = require("../node-type"); | ||
this._innerEval(this.text, document.URL); | ||
fireAnEvent("load", this); | ||
}, null, false, this); | ||
@@ -121,0 +118,0 @@ } |
@@ -23,2 +23,3 @@ "use strict"; | ||
} = require("../helpers/shadow-dom"); | ||
const { invalidateStyleCache } = require("../helpers/style-rules"); | ||
@@ -229,6 +230,7 @@ function nodeEquals(a, b) { | ||
this._clearMemoizedQueries(); | ||
invalidateStyleCache(this); | ||
} | ||
_childTextContentChangeSteps() { | ||
// Default: do nothing | ||
invalidateStyleCache(this); | ||
} | ||
@@ -235,0 +237,0 @@ |
{ | ||
"name": "jsdom", | ||
"version": "21.0.0", | ||
"version": "21.1.0", | ||
"description": "A JavaScript implementation of many web standards", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
2871073
473
76790