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