Skip to content

Commit 46b08ca

Browse files
committed
Update classes
1 parent 20b4ff0 commit 46b08ca

File tree

7 files changed

+123
-128
lines changed

7 files changed

+123
-128
lines changed

lib/CSSStyleDeclaration.js

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,14 @@ const { asciiLowercase } = require("./utils/strings");
2727
*/
2828
class CSSStyleDeclaration {
2929
/**
30-
* @param {object} context - Window, Element or CSSStyleRule
30+
* @param {object} globalObject - Window
3131
* @param {object} opt - Options
32-
* @param {object} opt.element - Required when the context is a Window
33-
* @param {string} opt.pseudoElement - Applies when the context is a Window
34-
* @param {Function} opt.onChange
35-
* - Executed when cssText changes or property is removed
36-
* - Applies when the context is an Element
32+
* @param {object} opt.context - Element or CSSStyleRule
33+
* @param {Function} opt.onChange - Callback when cssText change or property removed
3734
*/
38-
constructor(context = globalThis, opt = {}) {
39-
// Make constructor and internals non-enumerable.
35+
constructor(globalObject = globalThis, opt = {}) {
36+
// Make internals non-enumerable.
4037
Object.defineProperties(this, {
41-
constructor: {
42-
enumerable: false,
43-
writable: true
44-
},
45-
4638
// Window
4739
_global: {
4840
value: globalThis,
@@ -57,8 +49,8 @@ class CSSStyleDeclaration {
5749
writable: true
5850
},
5951

60-
// CSSRule
61-
_parentNode: {
52+
// CSSStyleRule
53+
_parentRule: {
6254
value: null,
6355
enumerable: false,
6456
writable: true
@@ -95,7 +87,7 @@ class CSSStyleDeclaration {
9587
},
9688

9789
_computed: {
98-
value: false,
90+
value: undefined,
9991
enumerable: false,
10092
writable: true
10193
},
@@ -106,39 +98,34 @@ class CSSStyleDeclaration {
10698
writable: true
10799
},
108100

109-
_setInProgress: {
101+
_updating: {
110102
value: false,
111103
enumerable: false,
112104
writable: true
113105
}
114106
});
115107

108+
this._global = globalObject;
109+
110+
const { context } = opt;
116111
if (context) {
117-
if (typeof context.getComputedStyle === "function") {
118-
this._global = context;
119-
this._computed = true;
120-
this._readonly = true;
121-
if (opt.element && opt.element.nodeType === 1) {
122-
this._ownerNode = opt.element;
123-
}
124-
} else if (context.nodeType === 1 && Object.hasOwn(context, "style")) {
125-
this._global = context.ownerDocument.defaultView;
112+
if (context.nodeType === 1) {
126113
this._ownerNode = context;
127-
if (typeof opt.onChange === "function") {
128-
this._onChange = opt.onChange;
129-
}
130114
} else if (Object.hasOwn(context, "parentRule")) {
131115
this._parentRule = context;
132-
// Find Window from the owner node of the StyleSheet.
133-
const window = context?.parentStyleSheet?.ownerNode?.ownerDocument?.defaultView;
134-
if (window) {
135-
this._global = window;
136-
}
137116
}
138117
}
139-
if (!Object.hasOwn(opt, "format")) {
118+
if (typeof opt.onChange === "function") {
119+
this._onChange = opt.onChange;
120+
}
121+
if (opt.format === "computedValue") {
122+
this._computed = true;
123+
} else {
140124
opt.format = "specifiedValue";
141125
}
126+
if (opt.readOnly) {
127+
this._readonly = true;
128+
}
142129
this._options = opt;
143130
}
144131

@@ -182,10 +169,10 @@ class CSSStyleDeclaration {
182169
Array.prototype.splice.call(this, 0, this._length);
183170
this._values.clear();
184171
this._priorities.clear();
185-
if (this._parentRule || (this._ownerNode && this._setInProgress)) {
172+
if (this._parentRule || (this._ownerNode && this._updating)) {
186173
return;
187174
}
188-
this._setInProgress = true;
175+
this._updating = true;
189176
try {
190177
const valueObj = parseCSS(
191178
val,
@@ -248,7 +235,7 @@ class CSSStyleDeclaration {
248235
} catch {
249236
return;
250237
}
251-
this._setInProgress = false;
238+
this._updating = false;
252239
if (typeof this._onChange === "function") {
253240
this._onChange(this.cssText);
254241
}
@@ -361,10 +348,18 @@ class CSSStyleDeclaration {
361348
return prevValue;
362349
}
363350

364-
// Readonly
365351
get parentRule() {
366352
return this._parentRule;
367353
}
354+
355+
// Non-standard
356+
get readOnly() {
357+
return this._readonly;
358+
}
359+
360+
set readOnly(bool) {
361+
this._readonly = Boolean(bool);
362+
}
368363
}
369364

370365
// Internal methods
@@ -408,7 +403,7 @@ Object.defineProperties(CSSStyleDeclaration.prototype, {
408403
if (
409404
typeof this._onChange === "function" &&
410405
this.cssText !== originalText &&
411-
!this._setInProgress
406+
!this._updating
412407
) {
413408
this._onChange(this.cssText);
414409
}

lib/CSSStyleProperties.js

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
const { CSSStyleDeclaration } = require("./CSSStyleDeclaration");
44
const generatedProperties = require("./generated/properties");
55
const propertyList = require("./generated/propertyList");
6-
const { dashedToCamelCase } = require("./utils/camelize");
76
const { getPropertyDescriptor } = require("./utils/propertyDescriptors");
87

98
/**
@@ -23,17 +22,13 @@ class CSSStyleProperties extends CSSStyleDeclaration {
2322
Object.defineProperties(CSSStyleProperties.prototype, generatedProperties);
2423

2524
// Additional properties
26-
for (const property of propertyList.keys()) {
25+
for (const definition of propertyList.values()) {
26+
const { legacyAliasOf, name, styleDeclaration } = definition;
27+
const property = legacyAliasOf ?? name;
2728
if (!Object.hasOwn(generatedProperties, property)) {
2829
const declaration = getPropertyDescriptor(property);
29-
Object.defineProperty(CSSStyleProperties.prototype, property, declaration);
30-
const camel = dashedToCamelCase(property);
31-
if (camel !== property) {
32-
Object.defineProperty(CSSStyleProperties.prototype, camel, declaration);
33-
if (/^webkit[A-Z]/.test(camel)) {
34-
const pascal = camel.replace(/^webkit/, "Webkit");
35-
Object.defineProperty(CSSStyleProperties.prototype, pascal, declaration);
36-
}
30+
for (const aliasProperty of styleDeclaration) {
31+
Object.defineProperty(CSSStyleProperties.prototype, aliasProperty, declaration);
3732
}
3833
}
3934
}

lib/utils/camelize.js renamed to scripts/camelize.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use strict";
22

3-
const { asciiLowercase } = require("./strings");
3+
const { asciiLowercase } = require("../lib/utils/strings");
44

55
// Utility to translate from `border-width` to `borderWidth`.
66
// NOTE: For values prefixed with webkit, e.g. `-webkit-foo`, we need to provide

scripts/generateProperties.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const t = require("@babel/types");
77
const generate = require("@babel/generator").default;
88
const traverse = require("@babel/traverse").default;
99
const resolve = require("resolve");
10-
const { camelCaseToDashed } = require("../lib/utils/camelize");
10+
const { camelCaseToDashed } = require("./camelize");
1111

1212
const { basename, dirname } = nodePath;
1313

test/CSSStyleDeclaration.test.js

Lines changed: 55 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ const assert = require("node:assert/strict");
55
const { CSSStyleDeclaration } = require("../lib/CSSStyleDeclaration");
66

77
describe("CSSStyleDeclaration", () => {
8-
it("does not enumerate constructor or internals", () => {
8+
it("does not enumerate internals", () => {
99
const style = new CSSStyleDeclaration();
10-
assert.strictEqual(Object.getOwnPropertyDescriptor(style, "constructor").enumerable, false);
1110
for (const i in style) {
1211
assert.strictEqual(i.startsWith("_"), false);
1312
}
@@ -31,69 +30,46 @@ describe("CSSStyleDeclaration", () => {
3130
assert.ok(style.__lookupGetter__("parentRule"));
3231
});
3332

34-
it("sets internals for Window", () => {
33+
it("sets internals for Element", () => {
3534
const window = {
36-
getComputedStyle: () => {},
3735
DOMException: globalThis.DOMException
3836
};
39-
const style = new CSSStyleDeclaration(window);
40-
assert.throws(
41-
() => {
42-
style.cssText = "color: green;";
43-
},
44-
(e) => {
45-
assert.strictEqual(e instanceof window.DOMException, true);
46-
assert.strictEqual(e.name, "NoModificationAllowedError");
47-
assert.strictEqual(e.message, "cssText can not be modified.");
48-
return true;
49-
}
50-
);
51-
assert.throws(
52-
() => {
53-
style.removeProperty("color");
54-
},
55-
(e) => {
56-
assert.strictEqual(e instanceof window.DOMException, true);
57-
assert.strictEqual(e.name, "NoModificationAllowedError");
58-
assert.strictEqual(e.message, "Property color can not be modified.");
59-
return true;
60-
}
61-
);
62-
});
63-
64-
it("sets internals for Element", () => {
6537
const node = {
6638
nodeType: 1,
6739
style: {},
6840
ownerDocument: {
69-
defaultView: {
70-
DOMException: globalThis.DOMException
71-
}
41+
defaultView: window
7242
}
7343
};
7444
let callCount = 0;
7545
const callback = () => {
7646
callCount++;
7747
};
78-
const style = new CSSStyleDeclaration(node, {
48+
const style = new CSSStyleDeclaration(window, {
49+
context: node,
7950
onChange: callback
8051
});
8152
style.cssText = "color: green;";
8253
assert.strictEqual(callCount, 1);
8354
});
8455

8556
it("sets internals for CSSRule", () => {
57+
const window = {
58+
DOMException: globalThis.DOMException
59+
};
8660
const rule = {
8761
parentRule: {},
8862
parentStyleSheet: {
8963
ownerDocument: {
9064
defaultView: {
91-
DOMException: globalThis.DOMException
65+
DOMException: window.DOMException
9266
}
9367
}
9468
}
9569
};
96-
const style = new CSSStyleDeclaration(rule);
70+
const style = new CSSStyleDeclaration(window, {
71+
context: rule
72+
});
9773
assert.deepEqual(style.parentRule, rule);
9874
});
9975

@@ -116,35 +92,19 @@ describe("CSSStyleDeclaration", () => {
11692
});
11793
});
11894

119-
it("getting cssText() returns empty string if computedflag is set", () => {
95+
it("getting cssText returns empty string if computedflag is set", () => {
12096
const window = {
12197
getComputedStyle: () => {},
12298
DOMException: globalThis.DOMException
12399
};
124-
const style = new CSSStyleDeclaration(window);
100+
const style = new CSSStyleDeclaration(window, {
101+
format: "computedValue"
102+
});
103+
style.cssText = "color: red;";
125104
assert.strictEqual(style.cssText, "");
126105
});
127106

128-
it("setting cssText() throws if readonly flag is set", () => {
129-
const window = {
130-
getComputedStyle: () => {},
131-
DOMException: globalThis.DOMException
132-
};
133-
const style = new CSSStyleDeclaration(window);
134-
assert.throws(
135-
() => {
136-
style.cssText = "color: green;";
137-
},
138-
(e) => {
139-
assert.strictEqual(e instanceof window.DOMException, true);
140-
assert.strictEqual(e.name, "NoModificationAllowedError");
141-
assert.strictEqual(e.message, "cssText can not be modified.");
142-
return true;
143-
}
144-
);
145-
});
146-
147-
it("setting improper css to csstext should not throw", () => {
107+
it("setting improper css to cssText should not throw", () => {
148108
const style = new CSSStyleDeclaration();
149109
style.cssText = "color: ";
150110
assert.strictEqual(style.cssText, "");
@@ -200,4 +160,41 @@ describe("CSSStyleDeclaration", () => {
200160

201161
assert.strictEqual(style.getPropertyValue("--baz"), "");
202162
});
163+
164+
it("getPropertyPriority for property", () => {
165+
const style = new CSSStyleDeclaration();
166+
style.setProperty("color", "green", "important");
167+
assert.strictEqual(style.getPropertyPriority("color"), "important");
168+
});
169+
170+
it("getPropertyPriority for custom property", () => {
171+
const style = new CSSStyleDeclaration();
172+
style.setProperty("--foo", "green", "important");
173+
assert.strictEqual(style.getPropertyPriority("--foo"), "important");
174+
});
175+
176+
it("removeProperty throws if readonly flag is set", () => {
177+
const window = {
178+
getComputedStyle: () => {},
179+
DOMException: globalThis.DOMException
180+
};
181+
const style = new CSSStyleDeclaration(window);
182+
assert.strictEqual(style.readOnly, false);
183+
style.setProperty("--foo", "green");
184+
style.setProperty("--bar", "red");
185+
assert.strictEqual(style.removeProperty("--foo"), "green");
186+
style.readOnly = true;
187+
assert.strictEqual(style.readOnly, true);
188+
assert.throws(
189+
() => {
190+
style.removeProperty("--bar");
191+
},
192+
(e) => {
193+
assert.strictEqual(e instanceof window.DOMException, true);
194+
assert.strictEqual(e.name, "NoModificationAllowedError");
195+
assert.strictEqual(e.message, "Property --bar can not be modified.");
196+
return true;
197+
}
198+
);
199+
});
203200
});

0 commit comments

Comments
 (0)