@@ -397,23 +397,20 @@ window.HTMLElement = (function HTMLElement(this: HTMLElement) {
397397window . HTMLElement . prototype = NativeHTMLElement . prototype ;
398398
399399// Helpers to return the scope for a node where its registry would be located
400- // const isValidScope = (node: Node) =>
401- // node === document || node instanceof ShadowRoot;
402- const registryForNode = ( node : Node ) : ShimmedCustomElementsRegistry | null => {
400+ const registryFromContext = (
401+ node : Element
402+ ) : ShimmedCustomElementsRegistry | null => {
403+ const explicitRegistry = registryForElement . get ( node ) ;
404+ if ( explicitRegistry != null ) {
405+ return explicitRegistry ;
406+ }
403407 const context = creationContext [ creationContext . length - 1 ] ;
404408 if ( context instanceof CustomElementRegistry ) {
405409 return context as ShimmedCustomElementsRegistry ;
406410 }
407- if (
408- context ?. nodeType === Node . ELEMENT_NODE ||
409- context ?. nodeType === Node . DOCUMENT_FRAGMENT_NODE
410- ) {
411- return context . customElements as ShimmedCustomElementsRegistry ;
412- }
413- return node . nodeType === Node . ELEMENT_NODE
414- ? ( ( node as Element ) . customElements as ShimmedCustomElementsRegistry ) ??
415- null
416- : null ;
411+ const registry = ( context as Element )
412+ . customElements as ShimmedCustomElementsRegistry ;
413+ return registry ?? null ;
417414} ;
418415
419416// Helper to create stand-in element for each tagName registered that delegates
@@ -440,7 +437,8 @@ const createStandInElement = (tagName: string): CustomElementConstructor => {
440437 // upgrade will eventually install the full CE prototype
441438 Object . setPrototypeOf ( instance , HTMLElement . prototype ) ;
442439 // Get the node's scope, and its registry (falls back to global registry)
443- const registry = registryForNode ( instance ) ;
440+ const registry = registryFromContext ( instance ) ;
441+ registryToSubtree ( instance , registry ) ;
444442 const definition = registry ?. _getDefinition ( tagName ) ;
445443 if ( definition ) {
446444 customize ( instance , definition ) ;
@@ -471,7 +469,8 @@ const createStandInElement = (tagName: string): CustomElementConstructor => {
471469 pendingRegistry . _upgradeWhenDefined ( this , tagName , true ) ;
472470 } else {
473471 const registry =
474- this . customElements ?? this . parentElement ?. customElements ;
472+ this . customElements ??
473+ ( this . parentNode as Element | ShadowRoot ) ?. customElements ;
475474 if ( registry ) {
476475 registryToSubtree (
477476 this ,
@@ -495,8 +494,8 @@ const createStandInElement = (tagName: string): CustomElementConstructor => {
495494 } else {
496495 // Un-register for upgrade when defined (so we don't leak)
497496 pendingRegistryForElement
498- . get ( this ) !
499- . _upgradeWhenDefined ( this , tagName , false ) ;
497+ . get ( this )
498+ ? ._upgradeWhenDefined ( this , tagName , false ) ;
500499 }
501500 }
502501
@@ -779,36 +778,57 @@ Object.defineProperty(
779778const creationContext : Array <
780779 Document | CustomElementRegistry | Element | ShadowRoot
781780> = [ document ] ;
782- const installScopedCreationMethod = (
781+ const installScopedMethod = (
783782 ctor : Function ,
784783 method : string ,
785- from ?: Document
784+ coda = function ( this : Element , result : Node ) {
785+ registryToSubtree (
786+ result ?? this ,
787+ this . customElements as ShimmedCustomElementsRegistry
788+ ) ;
789+ }
786790) => {
787- const native = ( from ? Object . getPrototypeOf ( from ) : ctor . prototype ) [ method ] ;
791+ const native = ctor . prototype [ method ] ;
792+ if ( native === undefined ) {
793+ return ;
794+ }
788795 ctor . prototype [ method ] = function (
789796 this : Element | ShadowRoot ,
790797 ...args : Array < unknown >
791798 ) {
792799 creationContext . push ( this ) ;
793- const ret = native . apply ( from || this , args ) ;
794- // For disconnected elements, note their creation scope so that e.g.
795- // innerHTML into them will use the correct scope; note that
796- // insertAdjacentHTML doesn't return an element, but that's fine since
797- // it will have a parent that should have a scope
798- if ( ret !== undefined ) {
799- registryToSubtree (
800- ret ,
801- this . customElements as ShimmedCustomElementsRegistry
802- ) ;
803- }
800+ const ret = native . apply ( this , args ) ;
804801 creationContext . pop ( ) ;
802+ coda ?. call ( this as Element , ret ) ;
805803 return ret ;
806804 } ;
807805} ;
808- installScopedCreationMethod ( Element , 'insertAdjacentHTML' ) ;
806+
807+ const applyScopeFromParent = function ( this : Element ) {
808+ const scope = ( this . parentNode ?? this ) as Element ;
809+ registryToSubtree (
810+ scope ,
811+ scope . customElements as ShimmedCustomElementsRegistry
812+ ) ;
813+ } ;
814+
815+ installScopedMethod ( Element , 'insertAdjacentHTML' , applyScopeFromParent ) ;
816+ installScopedMethod ( Element , 'setHTMLUnsafe' ) ;
817+ installScopedMethod ( ShadowRoot , 'setHTMLUnsafe' ) ;
818+
819+ // For setting null elements to this scope.
820+ installScopedMethod ( Node , 'appendChild' ) ;
821+ installScopedMethod ( Node , 'insertBefore' ) ;
822+ installScopedMethod ( Element , 'append' ) ;
823+ installScopedMethod ( Element , 'prepend' ) ;
824+ installScopedMethod ( Element , 'insertAdjacentElement' , applyScopeFromParent ) ;
825+ installScopedMethod ( Element , 'replaceChild' ) ;
826+ installScopedMethod ( Element , 'replaceChildren' ) ;
827+ installScopedMethod ( DocumentFragment , 'append' ) ;
828+ installScopedMethod ( Element , 'replaceWith' , applyScopeFromParent ) ;
809829
810830// Install scoped innerHTML on Element & ShadowRoot
811- const installScopedCreationSetter = ( ctor : Function , name : string ) => {
831+ const installScopedSetter = ( ctor : Function , name : string ) => {
812832 const descriptor = Object . getOwnPropertyDescriptor ( ctor . prototype , name ) ! ;
813833 Object . defineProperty ( ctor . prototype , name , {
814834 ...descriptor ,
@@ -820,8 +840,8 @@ const installScopedCreationSetter = (ctor: Function, name: string) => {
820840 } ,
821841 } ) ;
822842} ;
823- installScopedCreationSetter ( Element , 'innerHTML' ) ;
824- installScopedCreationSetter ( ShadowRoot , 'innerHTML' ) ;
843+ installScopedSetter ( Element , 'innerHTML' ) ;
844+ installScopedSetter ( ShadowRoot , 'innerHTML' ) ;
825845
826846// Install global registry
827847Object . defineProperty ( window , 'customElements' , {
0 commit comments