@@ -236,6 +236,10 @@ class Interface {
236
236
throw new Error ( msg ) ;
237
237
}
238
238
}
239
+
240
+ if ( utils . isGlobal ( this . idl ) && this . namedGetter ) {
241
+ this . factory = true ;
242
+ }
239
243
}
240
244
241
245
get supportsIndexedProperties ( ) {
@@ -347,15 +351,19 @@ class Interface {
347
351
` ;
348
352
}
349
353
354
+ if ( utils . isGlobal ( this . idl ) && this . supportsNamedProperties ) {
355
+ this . generateNamedPropertiesObject ( ) ;
356
+ this . str += `Object.setPrototypeOf(${ this . name } .prototype, namedPropertiesObject);` ;
357
+ } else if ( this . idl . inheritance ) {
358
+ this . str += `Object.setPrototypeOf(${ this . name } .prototype, ${ this . idl . inheritance } .interface.prototype);` ;
359
+ } else if ( utils . getExtAttr ( this . idl . extAttrs , "LegacyArrayClass" ) ) {
360
+ this . str += `Object.setPrototypeOf(${ this . name } .prototype, Array.prototype);` ;
361
+ }
362
+
350
363
if ( this . idl . inheritance ) {
351
364
this . str += `
352
- Object.setPrototypeOf(${ this . name } .prototype, ${ this . idl . inheritance } .interface.prototype);
353
365
Object.setPrototypeOf(${ this . name } , ${ this . idl . inheritance } .interface);
354
366
` ;
355
- } else if ( utils . getExtAttr ( this . idl . extAttrs , "LegacyArrayClass" ) ) {
356
- this . str += `
357
- Object.setPrototypeOf(${ this . name } .prototype, Array.prototype);
358
- ` ;
359
367
}
360
368
361
369
this . str += `
@@ -544,6 +552,180 @@ class Interface {
544
552
return conditions . join ( " && " ) ;
545
553
}
546
554
555
+ generateNamedPropertiesObject ( ) {
556
+ const proto = ( ( ) => {
557
+ if ( this . idl . inheritance ) {
558
+ return `${ this . idl . inheritance } .interface.prototype` ;
559
+ } else if ( utils . getExtAttr ( this . idl . extAttrs , "LegacyArrayClass" ) ) {
560
+ return "Array.prototype" ;
561
+ }
562
+ return "Object.prototype" ;
563
+ } ) ( ) ;
564
+
565
+ this . str += `
566
+ const namedPropertiesObject = new Proxy(Object.create(${ proto } , {
567
+ [Symbol.toStringTag]: {
568
+ value: "${ this . name } Properties",
569
+ writable: false,
570
+ enumerable: false,
571
+ configurable: true
572
+ }
573
+ }), {
574
+ ` ;
575
+
576
+ // [[SetPrototypeOf]]
577
+ this . str += `
578
+ setPrototypeOf() {
579
+ throw new TypeError("Immutable prototype object '#<${ this . name } Properties>' cannot have their prototype set");
580
+ },
581
+ ` ;
582
+
583
+ // [[PreventExtensions]]
584
+ this . str += `
585
+ preventExtensions() {
586
+ return false;
587
+ },
588
+ ` ;
589
+
590
+ // [[GetOwnProperty]]
591
+ this . str += `
592
+ getOwnPropertyDescriptor(target, P) {
593
+ if (typeof P === "symbol") {
594
+ return Reflect.getOwnPropertyDescriptor(target, P);
595
+ }
596
+ const object = defaultPrivateData.globalObject;
597
+ ` ;
598
+
599
+ const func = this . namedGetter . name !== null ? `.${ this . namedGetter . name } ` : "[utils.namedGet]" ;
600
+ const enumerable = ! utils . getExtAttr ( this . idl . extAttrs , "LegacyUnenumerableNamedProperties" ) ;
601
+ let preamble = "" ;
602
+ const conditions = [ ] ;
603
+ if ( utils . getExtAttr ( this . namedGetter . extAttrs , "WebIDL2JSValueAsUnsupported" ) ) {
604
+ this . str += `
605
+ const namedValue = object[impl]${ func } (P);
606
+ ` ;
607
+ conditions . push ( this . _supportsPropertyName ( "object" , "index" , "namedValue" ) ) ;
608
+ conditions . push ( this . _namedPropertyVisible ( "P" , "object" , true ) ) ;
609
+ } else {
610
+ preamble = `
611
+ const namedValue = object[impl]${ func } (P);
612
+ ` ;
613
+ conditions . push ( this . _namedPropertyVisible ( "P" , "object" , false ) ) ;
614
+ }
615
+
616
+ this . str += `
617
+ if (${ conditions . join ( " && " ) } ) {
618
+ ${ preamble }
619
+ return {
620
+ writable: true,
621
+ enumerable: ${ enumerable } ,
622
+ configurable: true,
623
+ value: utils.tryWrapperForImpl(namedValue)
624
+ };
625
+ }
626
+ return Reflect.getOwnPropertyDescriptor(target, P);
627
+ },
628
+ ` ;
629
+
630
+ // [[DefineOwnProperty]]
631
+ this . str += `
632
+ defineProperty() {
633
+ return false;
634
+ },
635
+ ` ;
636
+
637
+ // [[HasProperty]]
638
+ this . str += `
639
+ has(target, P) {
640
+ if (typeof P === "symbol") {
641
+ return Reflect.has(target, P);
642
+ }
643
+ const desc = this.getOwnPropertyDescriptor(target, P);
644
+ if (desc !== undefined) {
645
+ return true;
646
+ }
647
+ const parent = Object.getPrototypeOf(target);
648
+ if (parent !== null) {
649
+ return Reflect.has(parent, P);
650
+ }
651
+ return false;
652
+ },
653
+ ` ;
654
+
655
+ // [[Get]]
656
+ this . str += `
657
+ get(target, P, receiver) {
658
+ if (typeof P === "symbol") {
659
+ return Reflect.get(target, P, receiver);
660
+ }
661
+ const desc = this.getOwnPropertyDescriptor(target, P);
662
+ if (desc === undefined) {
663
+ const parent = Object.getPrototypeOf(target);
664
+ if (parent === null) {
665
+ return undefined;
666
+ }
667
+ return Reflect.get(target, P, receiver);
668
+ }
669
+ if (!desc.get && !desc.set) {
670
+ return desc.value;
671
+ }
672
+ const getter = desc.get;
673
+ if (getter === undefined) {
674
+ return undefined;
675
+ }
676
+ return Reflect.apply(getter, receiver, []);
677
+ },
678
+ ` ;
679
+
680
+ // [[Set]]
681
+ this . str += `
682
+ set(target, P, V, receiver) {
683
+ if (typeof P === "symbol") {
684
+ return Reflect.set(target, P, V, receiver);
685
+ }
686
+ const ownDesc = this.getOwnPropertyDescriptor(P);
687
+ if (ownDesc === undefined) {
688
+ const parent = Reflect.getPrototypeOf(target);
689
+ // parent is never null.
690
+ return Reflect.set(parent, P, V, receiver);
691
+ }
692
+ // ownDesc.writable is always true.
693
+ if (!utils.isObject(receiver)) {
694
+ return false;
695
+ }
696
+ // If receiver is this Proxy object, the following will always return false. Problem is, receiver may not be
697
+ // this Proxy object.
698
+ const existingDesc = Reflect.getOwnPropertyDescriptor(receiver, P);
699
+ let valueDesc;
700
+ if (existingDesc !== undefined) {
701
+ if (existingDesc.get || existingDesc.set) {
702
+ return false;
703
+ }
704
+ if (!existingDesc.writable) {
705
+ return false;
706
+ }
707
+ valueDesc = { value: V };
708
+ } else {
709
+ valueDesc = { writable: true, enumerable: true, configurable: true, value: V };
710
+ }
711
+ return Reflect.defineProperty(receiver, P, valueDesc);
712
+ },
713
+ ` ;
714
+
715
+ // [[Delete]]
716
+ this . str += `
717
+ deleteProperty() {
718
+ return false;
719
+ },
720
+ ` ;
721
+
722
+ // [[OwnPropertyKeys]] not overriden
723
+
724
+ this . str += `
725
+ });
726
+ ` ;
727
+ }
728
+
547
729
generateLegacyProxy ( ) {
548
730
const hasIndexedSetter = this . indexedSetter !== null ;
549
731
const hasNamedSetter = this . namedSetter !== null ;
0 commit comments