@@ -57,8 +57,6 @@ enum Intrinsic {
5757 DataView ,
5858 ValidateGuestChar ,
5959 ValidateHostChar ,
60- ValidateFlags ,
61- ValidateFlags64 ,
6260 /// Implementation of https://tc39.es/ecma262/#sec-toint32.
6361 ToInt32 ,
6462 /// Implementation of https://tc39.es/ecma262/#sec-touint32.
@@ -97,8 +95,6 @@ impl Intrinsic {
9795 Intrinsic :: DataView => "data_view" ,
9896 Intrinsic :: ValidateGuestChar => "validate_guest_char" ,
9997 Intrinsic :: ValidateHostChar => "validate_host_char" ,
100- Intrinsic :: ValidateFlags => "validate_flags" ,
101- Intrinsic :: ValidateFlags64 => "validate_flags64" ,
10298 Intrinsic :: ToInt32 => "to_int32" ,
10399 Intrinsic :: ToUint32 => "to_uint32" ,
104100 Intrinsic :: ToInt16 => "to_int16" ,
@@ -417,23 +413,14 @@ impl Generator for Js {
417413 docs : & Docs ,
418414 ) {
419415 self . docs ( docs) ;
420- let repr = js_flags_repr ( flags) ;
421- let ty = repr. ty ( ) ;
422- let suffix = repr. suffix ( ) ;
423416 self . src
424- . ts ( & format ! ( "export type {} = {ty};\n " , name. to_camel_case( ) ) ) ;
425- let name = name. to_shouty_snake_case ( ) ;
426- for ( i, flag) in flags. flags . iter ( ) . enumerate ( ) {
427- let flag = flag. name . to_shouty_snake_case ( ) ;
428- self . src . js ( & format ! (
429- "export const {name}_{flag} = {}{suffix};\n " ,
430- 1u128 << i,
431- ) ) ;
432- self . src . ts ( & format ! (
433- "export const {name}_{flag} = {}{suffix};\n " ,
434- 1u128 << i,
435- ) ) ;
417+ . ts ( & format ! ( "export interface {} {{\n " , name. to_camel_case( ) ) ) ;
418+ for flag in flags. flags . iter ( ) {
419+ self . docs ( & flag. docs ) ;
420+ let name = flag. name . to_mixed_case ( ) ;
421+ self . src . ts ( & format ! ( "{name}?: boolean,\n " ) ) ;
436422 }
423+ self . src . ts ( "}\n " ) ;
437424 }
438425
439426 fn type_variant (
@@ -1523,56 +1510,80 @@ impl Bindgen for FunctionBindgen<'_> {
15231510 results. push ( format ! ( "[{}]" , operands. join( ", " ) ) ) ;
15241511 }
15251512
1513+ // This lowers flags from a dictionary of booleans in accordance with https://webidl.spec.whatwg.org/#es-dictionary.
15261514 Instruction :: FlagsLower { flags, .. } => {
1527- let repr = js_flags_repr ( flags) ;
1528- let validate = match repr {
1529- JsFlagsRepr :: Number => self . gen . intrinsic ( Intrinsic :: ValidateFlags ) ,
1530- JsFlagsRepr :: Bigint => self . gen . intrinsic ( Intrinsic :: ValidateFlags64 ) ,
1531- } ;
15321515 let op0 = & operands[ 0 ] ;
1533- let len = flags. flags . len ( ) ;
1534- let n = repr. suffix ( ) ;
1535- let tmp = self . tmp ( ) ;
1536- let mask = ( 1u128 << len) - 1 ;
1516+
1517+ // Generate the result names.
1518+ for _ in 0 ..flags. repr ( ) . count ( ) {
1519+ let tmp = self . tmp ( ) ;
1520+ let name = format ! ( "flags{tmp}" ) ;
1521+ // Default to 0 so that in the null/undefined case, everything is false by
1522+ // default.
1523+ self . src . js ( & format ! ( "let {name} = 0;\n " ) ) ;
1524+ results. push ( name) ;
1525+ }
1526+
15371527 self . src . js ( & format ! (
1538- "const flags{tmp } = {validate}({ op0}, {mask}{n}); \n "
1528+ "if (typeof {op0 } === \" object \" && { op0} !== null) {{ \n "
15391529 ) ) ;
1540- match repr {
1541- JsFlagsRepr :: Number => {
1542- results. push ( format ! ( "flags{}" , tmp ) ) ;
1543- }
1544- JsFlagsRepr :: Bigint => {
1545- for i in 0 ..flags . repr ( ) . count ( ) {
1546- let i = 32 * i ;
1547- results . push ( format ! ( "Number((flags{tmp} >> {i}n) & 0xffffffffn)" , ) ) ;
1530+
1531+ for ( i , chunk ) in flags . flags . chunks ( 32 ) . enumerate ( ) {
1532+ let result_name = & results[ i ] ;
1533+
1534+ self . src . js ( & format ! ( "{result_name} = " ) ) ;
1535+ for ( i , flag ) in chunk . iter ( ) . enumerate ( ) {
1536+ if i != 0 {
1537+ self . src . js ( " | " ) ;
15481538 }
1539+
1540+ let flag = flag. name . to_mixed_case ( ) ;
1541+ self . src . js ( & format ! ( "Boolean({op0}.{flag}) << {i}" ) ) ;
15491542 }
1543+ self . src . js ( ";\n " ) ;
15501544 }
1545+
1546+ self . src . js ( & format ! ( "\
1547+ }} else if ({op0} !== null && {op0} !== undefined) {{
1548+ throw new TypeError(\" only an object, undefined or null can be converted to flags\" );
1549+ }}
1550+ " ) ) ;
1551+
1552+ // We don't need to do anything else for the null/undefined
1553+ // case, since that's interpreted as everything false, and we
1554+ // already defaulted everyting to 0.
15511555 }
15521556
15531557 Instruction :: FlagsLift { flags, .. } => {
1554- let repr = js_flags_repr ( flags) ;
1555- let n = repr. suffix ( ) ;
15561558 let tmp = self . tmp ( ) ;
1557- let operand = match repr {
1558- JsFlagsRepr :: Number => operands[ 0 ] . clone ( ) ,
1559- JsFlagsRepr :: Bigint => {
1560- self . src . js ( & format ! ( "let flags{tmp} = 0n;\n " ) ) ;
1561- for ( i, op) in operands. iter ( ) . enumerate ( ) {
1562- let i = 32 * i;
1563- self . src
1564- . js ( & format ! ( "flags{tmp} |= BigInt({op}) << {i}n;\n " , ) ) ;
1565- }
1566- format ! ( "flags{tmp}" )
1559+ results. push ( format ! ( "flags{tmp}" ) ) ;
1560+
1561+ if let Some ( op) = operands. last ( ) {
1562+ // We only need an extraneous bits check if the number of flags isn't a multiple
1563+ // of 32, because if it is then all the bits are used and there are no
1564+ // extraneous bits.
1565+ if flags. flags . len ( ) % 32 != 0 {
1566+ let mask: u32 = 0xffffffff << ( flags. flags . len ( ) % 32 ) ;
1567+ self . src . js ( & format ! (
1568+ "\
1569+ if (({op} & {mask}) !== 0) {{
1570+ throw new TypeError('flags have extraneous bits set');
1571+ }}
1572+ "
1573+ ) ) ;
15671574 }
1568- } ;
1569- let validate = match repr {
1570- JsFlagsRepr :: Number => self . gen . intrinsic ( Intrinsic :: ValidateFlags ) ,
1571- JsFlagsRepr :: Bigint => self . gen . intrinsic ( Intrinsic :: ValidateFlags64 ) ,
1572- } ;
1573- let len = flags. flags . len ( ) ;
1574- let mask = ( 1u128 << len) - 1 ;
1575- results. push ( format ! ( "{validate}({operand}, {mask}{n})" ) ) ;
1575+ }
1576+
1577+ self . src . js ( & format ! ( "const flags{tmp} = {{\n " ) ) ;
1578+
1579+ for ( i, flag) in flags. flags . iter ( ) . enumerate ( ) {
1580+ let flag = flag. name . to_mixed_case ( ) ;
1581+ let op = & operands[ i / 32 ] ;
1582+ let mask: u32 = 1 << ( i % 32 ) ;
1583+ self . src . js ( & format ! ( "{flag}: Boolean({op} & {mask}),\n " ) ) ;
1584+ }
1585+
1586+ self . src . js ( "};\n " ) ;
15761587 }
15771588
15781589 Instruction :: VariantPayloadName => results. push ( "e" . to_string ( ) ) ,
@@ -2309,26 +2320,6 @@ impl Js {
23092320 }
23102321 " ) ,
23112322
2312- Intrinsic :: ValidateFlags => self . src . js ( "
2313- export function validate_flags(flags, mask) {
2314- if (!Number.isInteger(flags)) \
2315- throw new TypeError('flags were not an integer');
2316- if ((flags & ~mask) != 0)
2317- throw new TypeError('flags have extraneous bits set');
2318- return flags;
2319- }
2320- " ) ,
2321-
2322- Intrinsic :: ValidateFlags64 => self . src . js ( "
2323- export function validate_flags64(flags, mask) {
2324- if (typeof flags !== 'bigint')
2325- throw new TypeError('flags were not a bigint');
2326- if ((flags & ~mask) != 0n)
2327- throw new TypeError('flags have extraneous bits set');
2328- return flags;
2329- }
2330- " ) ,
2331-
23322323
23332324 Intrinsic :: ToInt32 => self . src . js ( "
23342325 export function to_int32(val) {
@@ -2550,30 +2541,3 @@ impl Source {
25502541 self . ts . push_str ( s) ;
25512542 }
25522543}
2553-
2554- enum JsFlagsRepr {
2555- Number ,
2556- Bigint ,
2557- }
2558-
2559- impl JsFlagsRepr {
2560- fn ty ( & self ) -> & ' static str {
2561- match self {
2562- JsFlagsRepr :: Number => "number" ,
2563- JsFlagsRepr :: Bigint => "bigint" ,
2564- }
2565- }
2566- fn suffix ( & self ) -> & ' static str {
2567- match self {
2568- JsFlagsRepr :: Number => "" ,
2569- JsFlagsRepr :: Bigint => "n" ,
2570- }
2571- }
2572- }
2573-
2574- fn js_flags_repr ( f : & Flags ) -> JsFlagsRepr {
2575- match f. repr ( ) {
2576- FlagsRepr :: U8 | FlagsRepr :: U16 | FlagsRepr :: U32 ( 1 ) => JsFlagsRepr :: Number ,
2577- FlagsRepr :: U32 ( _) => JsFlagsRepr :: Bigint ,
2578- }
2579- }
0 commit comments