44 */
55"use strict" ;
66
7- const allProperties = require ( "./generated/allProperties" ) ;
8- const implementedProperties = require ( "./generated/implementedProperties" ) ;
9- const generatedProperties = require ( "./generated/properties" ) ;
7+ const propertyList = require ( "./generated/propertyList" ) ;
108const {
119 borderProperties,
1210 getPositionValue,
13- normalizeBorderProperties ,
11+ normalizeProperties ,
1412 prepareBorderProperties,
1513 prepareProperties,
1614 shorthandProperties
@@ -22,28 +20,21 @@ const {
2220 parsePropertyValue,
2321 prepareValue
2422} = require ( "./parsers" ) ;
25- const allExtraProperties = require ( "./utils/allExtraProperties" ) ;
26- const { dashedToCamelCase } = require ( "./utils/camelize" ) ;
27- const { getPropertyDescriptor } = require ( "./utils/propertyDescriptors" ) ;
2823const { asciiLowercase } = require ( "./utils/strings" ) ;
2924
3025/**
3126 * @see https://drafts.csswg.org/cssom/#the-cssstyledeclaration-interface
3227 */
3328class CSSStyleDeclaration {
3429 /**
35- * @param {Function } onChangeCallback
36- * @param {object } [opt]
37- * @param {object } [opt.context] - Window, Element or CSSRule.
30+ * @param {object } globalObject - Window
31+ * @param {object } opt - Options
32+ * @param {object } opt.context - Element or CSSStyleRule
33+ * @param {Function } opt.onChange - Callback when cssText change or property removed
3834 */
39- constructor ( onChangeCallback , opt = { } ) {
40- // Make constructor and internals non-enumerable.
35+ constructor ( globalObject = globalThis , opt = { } ) {
36+ // Make internals non-enumerable.
4137 Object . defineProperties ( this , {
42- constructor : {
43- enumerable : false ,
44- writable : true
45- } ,
46-
4738 // Window
4839 _global : {
4940 value : globalThis ,
@@ -58,8 +49,8 @@ class CSSStyleDeclaration {
5849 writable : true
5950 } ,
6051
61- // CSSRule
62- _parentNode : {
52+ // CSSStyleRule
53+ _parentRule : {
6354 value : null ,
6455 enumerable : false ,
6556 writable : true
@@ -71,6 +62,12 @@ class CSSStyleDeclaration {
7162 writable : true
7263 } ,
7364
65+ _options : {
66+ value : null ,
67+ enumerable : false ,
68+ writable : true
69+ } ,
70+
7471 _values : {
7572 value : new Map ( ) ,
7673 enumerable : false ,
@@ -90,7 +87,7 @@ class CSSStyleDeclaration {
9087 } ,
9188
9289 _computed : {
93- value : false ,
90+ value : undefined ,
9491 enumerable : false ,
9592 writable : true
9693 } ,
@@ -101,34 +98,35 @@ class CSSStyleDeclaration {
10198 writable : true
10299 } ,
103100
104- _setInProgress : {
101+ _updating : {
105102 value : false ,
106103 enumerable : false ,
107104 writable : true
108105 }
109106 } ) ;
110107
108+ this . _global = globalObject ;
109+
111110 const { context } = opt ;
112111 if ( context ) {
113- if ( typeof context . getComputedStyle === "function" ) {
114- this . _global = context ;
115- this . _computed = true ;
116- this . _readonly = true ;
117- } else if ( context . nodeType === 1 && Object . hasOwn ( context , "style" ) ) {
118- this . _global = context . ownerDocument . defaultView ;
112+ if ( context . nodeType === 1 ) {
119113 this . _ownerNode = context ;
120114 } else if ( Object . hasOwn ( context , "parentRule" ) ) {
121115 this . _parentRule = context ;
122- // Find Window from the owner node of the StyleSheet.
123- const window = context ?. parentStyleSheet ?. ownerNode ?. ownerDocument ?. defaultView ;
124- if ( window ) {
125- this . _global = window ;
126- }
127116 }
128117 }
129- if ( typeof onChangeCallback === "function" ) {
130- this . _onChange = onChangeCallback ;
118+ if ( typeof opt . onChange === "function" ) {
119+ this . _onChange = opt . onChange ;
120+ }
121+ if ( opt . format === "computedValue" ) {
122+ this . _computed = true ;
123+ } else {
124+ opt . format = "specifiedValue" ;
125+ }
126+ if ( opt . readOnly ) {
127+ this . _readonly = true ;
131128 }
129+ this . _options = opt ;
132130 }
133131
134132 get cssText ( ) {
@@ -150,7 +148,7 @@ class CSSStyleDeclaration {
150148 }
151149 properties . set ( property , { property, value, priority } ) ;
152150 }
153- const normalizedProperties = normalizeBorderProperties ( properties ) ;
151+ const normalizedProperties = normalizeProperties ( properties ) ;
154152 const parts = [ ] ;
155153 for ( const { property, value, priority } of normalizedProperties . values ( ) ) {
156154 if ( priority ) {
@@ -171,10 +169,10 @@ class CSSStyleDeclaration {
171169 Array . prototype . splice . call ( this , 0 , this . _length ) ;
172170 this . _values . clear ( ) ;
173171 this . _priorities . clear ( ) ;
174- if ( this . _parentRule || ( this . _ownerNode && this . _setInProgress ) ) {
172+ if ( this . _parentRule || ( this . _ownerNode && this . _updating ) ) {
175173 return ;
176174 }
177- this . _setInProgress = true ;
175+ this . _updating = true ;
178176 try {
179177 const valueObj = parseCSS (
180178 val ,
@@ -206,7 +204,8 @@ class CSSStyleDeclaration {
206204 }
207205 } else {
208206 const parsedValue = parsePropertyValue ( property , value , {
209- globalObject : this . _global
207+ globalObject : this . _global ,
208+ options : this . _options
210209 } ) ;
211210 if ( parsedValue ) {
212211 if ( properties . has ( property ) ) {
@@ -224,7 +223,8 @@ class CSSStyleDeclaration {
224223 }
225224 }
226225 const parsedProperties = prepareProperties ( properties , {
227- globalObject : this . _global
226+ globalObject : this . _global ,
227+ options : this . _options
228228 } ) ;
229229 for ( const [ property , item ] of parsedProperties ) {
230230 const { priority, value } = item ;
@@ -235,7 +235,7 @@ class CSSStyleDeclaration {
235235 } catch {
236236 return ;
237237 }
238- this . _setInProgress = false ;
238+ this . _updating = false ;
239239 if ( typeof this . _onChange === "function" ) {
240240 this . _onChange ( this . cssText ) ;
241241 }
@@ -255,36 +255,6 @@ class CSSStyleDeclaration {
255255 this . _length = len ;
256256 }
257257
258- // Readonly
259- get parentRule ( ) {
260- return this . _parentRule ;
261- }
262-
263- get cssFloat ( ) {
264- return this . getPropertyValue ( "float" ) ;
265- }
266-
267- set cssFloat ( value ) {
268- this . _setProperty ( "float" , value ) ;
269- }
270-
271- /**
272- * @param {string } property
273- */
274- getPropertyPriority ( property ) {
275- return this . _priorities . get ( property ) || "" ;
276- }
277-
278- /**
279- * @param {string } property
280- */
281- getPropertyValue ( property ) {
282- if ( this . _values . has ( property ) ) {
283- return this . _values . get ( property ) . toString ( ) ;
284- }
285- return "" ;
286- }
287-
288258 /**
289259 * @param {...number } args
290260 */
@@ -304,26 +274,18 @@ class CSSStyleDeclaration {
304274 /**
305275 * @param {string } property
306276 */
307- removeProperty ( property ) {
308- if ( this . _readonly ) {
309- const msg = `Property ${ property } can not be modified.` ;
310- const name = "NoModificationAllowedError" ;
311- throw new this . _global . DOMException ( msg , name ) ;
312- }
313- if ( ! this . _values . has ( property ) ) {
314- return "" ;
315- }
316- const prevValue = this . _values . get ( property ) ;
317- this . _values . delete ( property ) ;
318- this . _priorities . delete ( property ) ;
319- const index = Array . prototype . indexOf . call ( this , property ) ;
320- if ( index >= 0 ) {
321- Array . prototype . splice . call ( this , index , 1 ) ;
322- if ( typeof this . _onChange === "function" ) {
323- this . _onChange ( this . cssText ) ;
324- }
277+ getPropertyValue ( property ) {
278+ if ( this . _values . has ( property ) ) {
279+ return this . _values . get ( property ) . toString ( ) ;
325280 }
326- return prevValue ;
281+ return "" ;
282+ }
283+
284+ /**
285+ * @param {string } property
286+ */
287+ getPropertyPriority ( property ) {
288+ return this . _priorities . get ( property ) || "" ;
327289 }
328290
329291 /**
@@ -350,7 +312,7 @@ class CSSStyleDeclaration {
350312 return ;
351313 }
352314 const property = asciiLowercase ( prop ) ;
353- if ( ! allProperties . has ( property ) && ! allExtraProperties . has ( property ) ) {
315+ if ( ! propertyList . has ( property ) ) {
354316 return ;
355317 }
356318 if ( priority ) {
@@ -360,6 +322,45 @@ class CSSStyleDeclaration {
360322 }
361323 this [ property ] = value ;
362324 }
325+
326+ /**
327+ * @param {string } property
328+ */
329+ removeProperty ( property ) {
330+ if ( this . _readonly ) {
331+ const msg = `Property ${ property } can not be modified.` ;
332+ const name = "NoModificationAllowedError" ;
333+ throw new this . _global . DOMException ( msg , name ) ;
334+ }
335+ if ( ! this . _values . has ( property ) ) {
336+ return "" ;
337+ }
338+ const prevValue = this . _values . get ( property ) ;
339+ this . _values . delete ( property ) ;
340+ this . _priorities . delete ( property ) ;
341+ const index = Array . prototype . indexOf . call ( this , property ) ;
342+ if ( index >= 0 ) {
343+ Array . prototype . splice . call ( this , index , 1 ) ;
344+ if ( typeof this . _onChange === "function" ) {
345+ this . _onChange ( this . cssText ) ;
346+ }
347+ }
348+ return prevValue ;
349+ }
350+
351+ get parentRule ( ) {
352+ return this . _parentRule ;
353+ }
354+
355+ // Non-standard
356+ setOptions ( opt = { } ) {
357+ for ( const [ key , value ] of Object . entries ( opt ) ) {
358+ this . _options [ key ] = value ;
359+ if ( key === "readOnly" ) {
360+ this . _readonly = value ;
361+ }
362+ }
363+ }
363364}
364365
365366// Internal methods
@@ -403,7 +404,7 @@ Object.defineProperties(CSSStyleDeclaration.prototype, {
403404 if (
404405 typeof this . _onChange === "function" &&
405406 this . cssText !== originalText &&
406- ! this . _setInProgress
407+ ! this . _updating
407408 ) {
408409 this . _onChange ( this . cssText ) ;
409410 }
@@ -442,7 +443,8 @@ Object.defineProperties(CSSStyleDeclaration.prototype, {
442443 }
443444 }
444445 const parsedProperties = prepareBorderProperties ( prop , val , prior , properties , {
445- globalObject : this . _global
446+ globalObject : this . _global ,
447+ options : this . _options
446448 } ) ;
447449 for ( const [ property , item ] of parsedProperties ) {
448450 const { priority, value } = item ;
@@ -507,8 +509,10 @@ Object.defineProperties(CSSStyleDeclaration.prototype, {
507509 }
508510 } else {
509511 const parsedValue = shorthandItem . parse ( longhandValues . join ( " " ) ) ;
510- const shorthandValue = Object . values ( parsedValue ) . join ( " " ) ;
511- this . _setProperty ( shorthandProperty , shorthandValue , priority ) ;
512+ if ( parsedValue ) {
513+ const shorthandValue = Object . values ( parsedValue ) . join ( " " ) ;
514+ this . _setProperty ( shorthandProperty , shorthandValue , priority ) ;
515+ }
512516 }
513517 }
514518 }
@@ -605,32 +609,14 @@ Object.defineProperties(CSSStyleDeclaration.prototype, {
605609 }
606610 if ( longhandValues . length === shorthandFor . size ) {
607611 const replacedValue = getPositionValue ( longhandValues , shorthandPosition ) ;
608- this . _setProperty ( shorthandProperty , replacedValue ) ;
612+ this . _setProperty ( shorthandProperty , replacedValue , priority ) ;
609613 }
610614 }
611615 } ,
612616 enumerable : false
613617 }
614618} ) ;
615619
616- // Properties
617- Object . defineProperties ( CSSStyleDeclaration . prototype , generatedProperties ) ;
618-
619- // Additional properties
620- [ ...allProperties , ...allExtraProperties ] . forEach ( ( property ) => {
621- if ( ! implementedProperties . has ( property ) ) {
622- const declaration = getPropertyDescriptor ( property ) ;
623- Object . defineProperty ( CSSStyleDeclaration . prototype , property , declaration ) ;
624- const camel = dashedToCamelCase ( property ) ;
625- Object . defineProperty ( CSSStyleDeclaration . prototype , camel , declaration ) ;
626- if ( / ^ w e b k i t [ A - Z ] / . test ( camel ) ) {
627- const pascal = camel . replace ( / ^ w e b k i t / , "Webkit" ) ;
628- Object . defineProperty ( CSSStyleDeclaration . prototype , pascal , declaration ) ;
629- }
630- }
631- } ) ;
632-
633620module . exports = {
634- CSSStyleDeclaration,
635- propertyList : Object . fromEntries ( implementedProperties )
621+ CSSStyleDeclaration
636622} ;
0 commit comments