@@ -14,6 +14,14 @@ function isSimpleIDLType(idlType, expected) {
1414 return idlType . idlType === expected ;
1515}
1616
17+ const recognizedReflectXAttrNames = new Set ( [
18+ "Reflect" ,
19+ "ReflectURL" ,
20+ "ReflectNonNegative" ,
21+ "ReflectPositive" ,
22+ "ReflectPositiveWithFallback"
23+ ] ) ;
24+
1725const transformer = new Webidl2js ( {
1826 implSuffix : "-impl" ,
1927 suppressErrors : true ,
@@ -39,19 +47,22 @@ const transformer = new Webidl2js({
3947 } ,
4048 // https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes
4149 processReflect ( idl , implObj ) {
42- const reflectAttr = idl . extAttrs . find (
43- attr => attr . name === "Reflect" || attr . name === "ReflectURL" || attr . name === "ReflectNonNegative"
44- ) ;
50+ const reflectAttr = idl . extAttrs . find ( attr => recognizedReflectXAttrNames . has ( attr . name ) ) ;
4551 const attrName = reflectAttr ?. rhs ? JSON . parse ( reflectAttr . rhs . value ) : idl . name . toLowerCase ( ) ;
4652
47- // TODO: [ReflectDefault] is only used for `long` right now; also use it for `unsigned long` and `double`.
4853 const reflectDefaultAttr = idl . extAttrs . find ( attr => attr . name === "ReflectDefault" ) ;
4954 const reflectDefault = reflectDefaultAttr ?. rhs ? JSON . parse ( reflectDefaultAttr . rhs . value ) : undefined ;
5055
56+ const reflectRangeAttr = idl . extAttrs . find ( attr => attr . name === "ReflectRange" ) ;
57+ const reflectRange = reflectRangeAttr ?. rhs ? reflectRangeAttr . rhs . value . map ( v => JSON . parse ( v . value ) ) : undefined ;
58+ if ( reflectRange && reflectRange . length !== 2 ) {
59+ throw new Error ( "Invalid [ReflectRange] value" ) ;
60+ }
61+
5162 if ( reflectAttr . name === "ReflectURL" ) {
5263 // Allow DOMString also due to https://github.com/whatwg/html/issues/5241.
5364 if ( ! isSimpleIDLType ( idl . idlType , "USVString" ) && ! isSimpleIDLType ( idl . idlType , "DOMString" ) ) {
54- throw new Error ( "[ReflectURL] specified on non-USV/ DOMString attribute" ) ;
65+ throw new Error ( "[ReflectURL] specified on non-USVString, non- DOMString IDL attribute" ) ;
5566 }
5667 const parseURLToResultingURLRecord =
5768 this . addImport ( "../helpers/document-base-url" , "parseURLToResultingURLRecord" ) ;
@@ -74,11 +85,21 @@ const transformer = new Webidl2js({
7485 } ;
7586 }
7687
88+ // For all these cases, we'll process them later, but we do the checks now.
7789 if ( reflectAttr . name === "ReflectNonNegative" ) {
7890 if ( ! isSimpleIDLType ( idl . idlType , "long" ) ) {
79- throw new Error ( "[ReflectNonNegative] specified on non-long attribute" ) ;
91+ throw new Error ( "[ReflectNonNegative] specified on non-long IDL attribute" ) ;
92+ }
93+ }
94+ if ( reflectAttr . name === "ReflectPositive" ) {
95+ if ( ! isSimpleIDLType ( idl . idlType , "unsigned long" ) && ! isSimpleIDLType ( idl . idlType , "double" ) ) {
96+ throw new Error ( "[ReflectPositive] specified on non-unsigned long, non-double IDL attribute" ) ;
97+ }
98+ }
99+ if ( reflectAttr . name === "ReflectPositiveWithFallback" ) {
100+ if ( ! isSimpleIDLType ( idl . idlType , "unsigned long" ) ) {
101+ throw new Error ( "[ReflectPositiveWithFallback] specified on non-unsigned long IDL attribute" ) ;
80102 }
81- // We'll actually do the processing in the long case, later.
82103 }
83104
84105 if ( isSimpleIDLType ( idl . idlType , "DOMString" ) || isSimpleIDLType ( idl . idlType , "USVString" ) ) {
@@ -174,18 +195,107 @@ const transformer = new Webidl2js({
174195 if ( isSimpleIDLType ( idl . idlType , "unsigned long" ) ) {
175196 const parseNonNegativeInteger = this . addImport ( "../helpers/strings" , "parseNonNegativeInteger" ) ;
176197
198+ const minimum = reflectAttr . name === "ReflectPositive" || reflectAttr . name === "ReflectPositiveWithFallback" ?
199+ 1 :
200+ 0 ;
201+ const maximum = 2147483647 ;
202+ const defaultValue = reflectDefault !== undefined ? reflectDefault : minimum ;
203+
204+ let setterPrefix = "" ;
205+ if ( reflectAttr . name === "ReflectPositive" ) {
206+ const createDOMException = this . addImport ( "./DOMException" , "create" ) ;
207+ setterPrefix = `
208+ if (V === 0) {
209+ throw ${ createDOMException } (
210+ globalObject,
211+ [\`The value \${V} cannot be set for the ${ idl . name } property.\`, "IndexSizeError"]
212+ );
213+ }
214+ ` ;
215+ }
216+
217+ let get ;
218+ if ( reflectRange ) {
219+ const clampedMinimum = reflectRange [ 0 ] ;
220+ const clampedMaximum = reflectRange [ 1 ] ;
221+ const clampedDefaultValue = reflectDefault !== undefined ? reflectDefault : clampedMinimum ;
222+
223+ get = `
224+ let value = ${ implObj } ._reflectGetTheContentAttribute("${ attrName } ");
225+ if (value !== null) {
226+ value = ${ parseNonNegativeInteger } (value);
227+ if (value !== null) {
228+ if (value < ${ clampedMinimum } ) {
229+ return ${ clampedMinimum } ;
230+ } else if (value >= ${ clampedMinimum } && value <= ${ clampedMaximum } ) {
231+ return value;
232+ } else {
233+ return ${ clampedMaximum } ;
234+ }
235+ }
236+ }
237+ return ${ clampedDefaultValue } ;
238+ ` ;
239+ } else {
240+ get = `
241+ let value = ${ implObj } ._reflectGetTheContentAttribute("${ attrName } ");
242+ if (value !== null) {
243+ value = ${ parseNonNegativeInteger } (value);
244+ if (value !== null && value >= ${ minimum } && value <= ${ maximum } ) {
245+ return value;
246+ }
247+ }
248+ return ${ defaultValue } ;
249+ ` ;
250+ }
251+
252+ return {
253+ get,
254+ set : `
255+ ${ setterPrefix }
256+ const newValue = V <= ${ maximum } && V >= ${ minimum } ? V : ${ defaultValue } ;
257+ ${ implObj } ._reflectSetTheContentAttribute("${ attrName } ", String(newValue));
258+ `
259+ } ;
260+ }
261+
262+ if ( isSimpleIDLType ( idl . idlType , "double" ) ) {
263+ const parseFloatingPointNumber = this . addImport ( "../helpers/strings" , "parseFloatingPointNumber" ) ;
264+ const defaultValue = reflectDefault !== undefined ? reflectDefault : 0 ;
265+
266+ if ( reflectAttr . name === "ReflectPositive" ) {
267+ return {
268+ get : `
269+ let value = ${ implObj } ._reflectGetTheContentAttribute("${ attrName } ");
270+ if (value !== null) {
271+ value = ${ parseFloatingPointNumber } (value);
272+ if (value !== null && value > 0) {
273+ return value;
274+ }
275+ }
276+ return ${ defaultValue } ;
277+ ` ,
278+ set : `
279+ if (V > 0) {
280+ ${ implObj } ._reflectSetTheContentAttribute("${ attrName } ", String(V));
281+ }
282+ `
283+ } ;
284+ }
285+
177286 return {
178287 get : `
179288 let value = ${ implObj } ._reflectGetTheContentAttribute("${ attrName } ");
180- if (value === null) {
181- return 0;
289+ if (value !== null) {
290+ value = ${ parseFloatingPointNumber } (value);
291+ if (value !== null) {
292+ return value;
293+ }
182294 }
183- value = ${ parseNonNegativeInteger } (value);
184- return value !== null && value >= 0 && value <= 2147483647 ? value : 0;
295+ return ${ defaultValue } ;
185296 ` ,
186297 set : `
187- const n = V <= 2147483647 ? V : 0;
188- ${ implObj } ._reflectSetTheContentAttribute("${ attrName } ", String(n));
298+ ${ implObj } ._reflectSetTheContentAttribute("${ attrName } ", String(V));
189299 `
190300 } ;
191301 }
0 commit comments