Skip to content

Commit 1a3321e

Browse files
committed
Update classes
1 parent 20b4ff0 commit 1a3321e

File tree

7 files changed

+124
-126
lines changed

7 files changed

+124
-126
lines changed

lib/CSSStyleDeclaration.js

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,17 @@ const { asciiLowercase } = require("./utils/strings");
2727
*/
2828
class CSSStyleDeclaration {
2929
/**
30-
* @param {object} context - Window, Element or CSSStyleRule
30+
* @param {object} globalObject
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
32+
* @param {object} opt.context - Element or CSSStyleRule
33+
* @param {string} opt.pseudoElement - Not yet implemented
3434
* @param {Function} opt.onChange
35-
* - Executed when cssText changes or property is removed
3635
* - Applies when the context is an Element
36+
* - Executed when cssText changes or property is removed
3737
*/
38-
constructor(context = globalThis, opt = {}) {
39-
// Make constructor and internals non-enumerable.
38+
constructor(globalObject = globalThis, opt = {}) {
39+
// Make internals non-enumerable.
4040
Object.defineProperties(this, {
41-
constructor: {
42-
enumerable: false,
43-
writable: true
44-
},
45-
4641
// Window
4742
_global: {
4843
value: globalThis,
@@ -57,8 +52,8 @@ class CSSStyleDeclaration {
5752
writable: true
5853
},
5954

60-
// CSSRule
61-
_parentNode: {
55+
// CSSStyleRule
56+
_parentRule: {
6257
value: null,
6358
enumerable: false,
6459
writable: true
@@ -95,7 +90,7 @@ class CSSStyleDeclaration {
9590
},
9691

9792
_computed: {
98-
value: false,
93+
value: undefined,
9994
enumerable: false,
10095
writable: true
10196
},
@@ -106,39 +101,34 @@ class CSSStyleDeclaration {
106101
writable: true
107102
},
108103

109-
_setInProgress: {
104+
_updating: {
110105
value: false,
111106
enumerable: false,
112107
writable: true
113108
}
114109
});
115110

111+
this._global = globalObject;
112+
113+
const { context } = opt;
116114
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;
115+
if (context.nodeType === 1) {
126116
this._ownerNode = context;
127-
if (typeof opt.onChange === "function") {
128-
this._onChange = opt.onChange;
129-
}
130117
} else if (Object.hasOwn(context, "parentRule")) {
131118
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-
}
137119
}
138120
}
139-
if (!Object.hasOwn(opt, "format")) {
121+
if (typeof opt.onChange === "function") {
122+
this._onChange = opt.onChange;
123+
}
124+
if (opt.format === "computedValue") {
125+
this._computed = true;
126+
} else {
140127
opt.format = "specifiedValue";
141128
}
129+
if (opt.readOnly) {
130+
this._readonly = true;
131+
}
142132
this._options = opt;
143133
}
144134

@@ -182,10 +172,10 @@ class CSSStyleDeclaration {
182172
Array.prototype.splice.call(this, 0, this._length);
183173
this._values.clear();
184174
this._priorities.clear();
185-
if (this._parentRule || (this._ownerNode && this._setInProgress)) {
175+
if (this._parentRule || (this._ownerNode && this._updating)) {
186176
return;
187177
}
188-
this._setInProgress = true;
178+
this._updating = true;
189179
try {
190180
const valueObj = parseCSS(
191181
val,
@@ -248,7 +238,7 @@ class CSSStyleDeclaration {
248238
} catch {
249239
return;
250240
}
251-
this._setInProgress = false;
241+
this._updating = false;
252242
if (typeof this._onChange === "function") {
253243
this._onChange(this.cssText);
254244
}
@@ -361,10 +351,18 @@ class CSSStyleDeclaration {
361351
return prevValue;
362352
}
363353

364-
// Readonly
365354
get parentRule() {
366355
return this._parentRule;
367356
}
357+
358+
// Non-standard
359+
get readOnly() {
360+
return this._readonly;
361+
}
362+
363+
set readOnly(bool) {
364+
this._readonly = Boolean(bool);
365+
}
368366
}
369367

370368
// Internal methods
@@ -408,7 +406,7 @@ Object.defineProperties(CSSStyleDeclaration.prototype, {
408406
if (
409407
typeof this._onChange === "function" &&
410408
this.cssText !== originalText &&
411-
!this._setInProgress
409+
!this._updating
412410
) {
413411
this._onChange(this.cssText);
414412
}

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)