@webqit/oohtml 4.0.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "wicg-proposal"
15
15
  ],
16
16
  "homepage": "https://webqit.io/tooling/oohtml",
17
- "version": "4.0.2",
17
+ "version": "4.1.0",
18
18
  "license": "MIT",
19
19
  "repository": {
20
20
  "type": "git",
@@ -26,6 +26,10 @@
26
26
  "type": "module",
27
27
  "sideEffects": true,
28
28
  "main": "./src/index.js",
29
+ "exports": {
30
+ ".": "./src/index.js",
31
+ "./lite": "./src/index.lite.js"
32
+ },
29
33
  "scripts": {
30
34
  "test": "mocha --extension .test.js --exit",
31
35
  "test:coverage": "c8 --reporter=text-lcov npm run test | coveralls",
@@ -35,8 +39,8 @@
35
39
  "postpublish": "git push && git push --tags"
36
40
  },
37
41
  "dependencies": {
38
- "@webqit/quantum-js": "^4.5.2",
39
- "@webqit/realdom": "^2.1.23",
42
+ "@webqit/quantum-js": "^4.5.5",
43
+ "@webqit/realdom": "^2.1.24",
40
44
  "@webqit/util": "^0.8.11"
41
45
  },
42
46
  "devDependencies": {
@@ -39,11 +39,11 @@ export default class DOMBindingsContext extends DOMContext {
39
39
  * @handle()
40
40
  */
41
41
  handle( event ) {
42
- // Any existing event._controller? Abort!
43
- event._controller?.abort();
42
+ // Any existing event.meta.controller? Abort!
43
+ event.meta.controller?.abort();
44
44
  if ( !( event.detail + '' ).trim() ) return event.respondWith( this.bindingsObj );
45
45
  const { window: { webqit: { Observer } } } = env;
46
- event._controller = Observer.reduce( this.bindingsObj, Array.isArray( event.detail ) ? event.detail : [ event.detail ], Observer.get, descriptor => {
46
+ event.meta.controller = Observer.reduce( this.bindingsObj, Array.isArray( event.detail ) ? event.detail : [ event.detail ], Observer.get, descriptor => {
47
47
  if ( this.disposed ) return; // If already scheduled but aborted as in provider unmounting
48
48
  event.respondWith( descriptor.value );
49
49
  }, { live: event.live, signal: event.signal, descripted: true } );
@@ -52,5 +52,5 @@ export default class DOMBindingsContext extends DOMContext {
52
52
  /**
53
53
  * @unsubscribed()
54
54
  */
55
- unsubscribed( event ) { event._controller?.abort(); }
55
+ unsubscribed( event ) { event.meta.controller?.abort(); }
56
56
  }
@@ -33,12 +33,12 @@ function getBindings( config, node ) {
33
33
  Observer.observe( bindingsObj, mutations => {
34
34
  // Reflection
35
35
  const props = Object.keys( bindingsObj );
36
- const targetNode = node === window.document ? window.document.documentElement : node;
36
+ const reflectionTargetNode = node instanceof window.Document ? node.documentElement : node;
37
37
  const bindingsReflection = config.attr.bindingsreflection;
38
- if ( props.length && bindingsReflection ) {
39
- targetNode.setAttribute( config.attr.bindingsreflection, props.join( ' ') );
40
- } else if ( bindingsReflection ) {
41
- targetNode.toggleAttribute( config.attr.bindingsreflection, false );
38
+ if ( props.length && bindingsReflection && reflectionTargetNode.setAttribute ) {
39
+ reflectionTargetNode.setAttribute( config.attr.bindingsreflection, props.join( ' ') );
40
+ } else if ( bindingsReflection && reflectionTargetNode.setAttribute ) {
41
+ reflectionTargetNode.toggleAttribute( config.attr.bindingsreflection, false );
42
42
  }
43
43
  // Re: DOMBindingsContext
44
44
  const contextsApi = node[ ctxConfig.api.contexts ];
@@ -64,24 +64,20 @@ function getBindings( config, node ) {
64
64
  */
65
65
  function exposeAPIs( config ) {
66
66
  const window = this, { webqit: { Observer } } = window;
67
- // Assertions
68
- if ( config.api.bind in window.document ) { throw new Error( `document already has a "${ config.api.bind }" property!` ); }
69
- if ( config.api.bindings in window.document ) { throw new Error( `document already has a "${ config.api.bindings }" property!` ); }
70
- if ( config.api.bind in window.Element.prototype ) { throw new Error( `The "Element" class already has a "${ config.api.bind }" property!` ); }
71
- if ( config.api.bindings in window.Element.prototype ) { throw new Error( `The "Element" class already has a "${ config.api.bindings }" property!` ); }
72
- // Definitions
73
- Object.defineProperty( window.document, config.api.bind, { value: function( bindings, options = {} ) {
74
- return applyBindings.call( window, config, window.document, bindings, options );
75
- } });
76
- Object.defineProperty( window.document, config.api.bindings, { get: function() {
77
- return Observer.proxy( getBindings.call( window, config, window.document ) );
78
- } });
79
- Object.defineProperty( window.Element.prototype, config.api.bind, { value: function( bindings, options = {} ) {
80
- return applyBindings.call( window, config, this, bindings, options );
81
- } });
82
- Object.defineProperty( window.Element.prototype, config.api.bindings, { get: function() {
83
- return Observer.proxy( getBindings.call( window, config, this ) );
84
- } } );
67
+ // The Bindings APIs
68
+ [ window.Document.prototype, window.Element.prototype, window.ShadowRoot.prototype ].forEach( prototype => {
69
+ // No-conflict assertions
70
+ const type = prototype === window.Document.prototype ? 'Document' : ( prototype === window.ShadowRoot.prototype ? 'ShadowRoot' : 'Element' );
71
+ if ( config.api.bind in prototype ) { throw new Error( `The ${ type } prototype already has a "${ config.api.bind }" API!` ); }
72
+ if ( config.api.bindings in prototype ) { throw new Error( `The ${ type } prototype already has a "${ config.api.bindings }" API!` ); }
73
+ // Definitions
74
+ Object.defineProperty( prototype, config.api.bind, { value: function( bindings, options = {} ) {
75
+ return applyBindings.call( window, config, this, bindings, options );
76
+ } });
77
+ Object.defineProperty( prototype, config.api.bindings, { get: function() {
78
+ return Observer.proxy( getBindings.call( window, config, this ) );
79
+ } } );
80
+ } );
85
81
  }
86
82
 
87
83
  /**
@@ -36,7 +36,7 @@ export default class DOMContext {
36
36
  /**
37
37
  * @name
38
38
  */
39
- get name() { return this.host === env.window.document ? Infinity : this.host.getAttribute( this.configs.CONTEXT_API.attr.contextname ); }
39
+ get name() { return [ env.window.Document, env.window.ShadowRoot ].some( x => this.host instanceof x ) ? Infinity : this.host.getAttribute( this.configs.CONTEXT_API.attr.contextname ); }
40
40
 
41
41
  /**
42
42
  * @subscribed()
@@ -67,15 +67,15 @@ export default class DOMContext {
67
67
  handleEvent( event ) {
68
68
  if ( this.disposed || typeof event.respondWith !== 'function' ) return;
69
69
  if ( event.type === 'contextclaim' ) {
70
- if ( event.target === this.host || !( event.detail instanceof DOMContext ) ) return;
70
+ if ( !( event.detail instanceof DOMContext ) || event.target === this.host ) return;
71
71
  const claims = new Set;
72
72
  this.subscriptions.forEach( subscriptionEvent => {
73
73
  if ( !event.target.contains( subscriptionEvent.target ) || !event.detail.matchEvent( subscriptionEvent ) ) return;
74
- event.stopPropagation();
75
74
  this.subscriptions.delete( subscriptionEvent );
75
+ this.unsubscribed( subscriptionEvent );
76
76
  claims.add( subscriptionEvent );
77
77
  } );
78
- return event.respondWith( claims );
78
+ if ( claims.size ) { return event.respondWith( claims ); }
79
79
  }
80
80
  if ( event.type === 'contextrequest' ) {
81
81
  if ( !this.matchEvent( event ) ) return;
@@ -8,6 +8,7 @@ import DOMContext from './DOMContext.js';
8
8
  import DuplicateContextError from './DuplicateContextError.js';
9
9
  import { _ } from '../util.js';
10
10
 
11
+ const waitListMappings = new Map;
11
12
  export default class DOMContexts {
12
13
 
13
14
  /**
@@ -76,13 +77,35 @@ export default class DOMContexts {
76
77
  if ( !args[ args.length - 1 ] ) { args[ args.length - 1 ] = emitter; }
77
78
  else { args.push( emitter ); }
78
79
  }
80
+
79
81
  let options;
80
82
  if ( ( options = args.find( arg => typeof arg === 'object' && arg ) ) && options.live ) {
81
83
  if ( options.signal ) options.signal.addEventListener( 'abort', () => responseInstance.abort() );
82
84
  args[ args.indexOf( options ) ] = { ...options, signal: responseInstance.signal };
83
85
  }
84
86
  const event = new ( _DOMContextRequestEvent() )( ...args );
85
- this[ '#' ].host.dispatchEvent( event );
87
+
88
+ const rootNode = this[ '#' ].host.getRootNode();
89
+ const temp = event => {
90
+ if ( event.answered ) return;
91
+ event.meta.target = event.target;
92
+ if ( !waitListMappings.get( rootNode ) ) { waitListMappings.set( rootNode, new Set ); }
93
+ if ( event.type === 'contextrequest' && event.live ) {
94
+ waitListMappings.get( rootNode ).add( event );
95
+ } else if ( event.type === 'contextclaim' ) {
96
+ const claims = new Set;
97
+ waitListMappings.get( rootNode ).forEach( subscriptionEvent => {
98
+ if ( !this[ '#' ].host.contains( subscriptionEvent.target ) || !event.detail.matchEvent( subscriptionEvent ) ) return;
99
+ waitListMappings.get( rootNode ).delete( subscriptionEvent );
100
+ claims.add( subscriptionEvent );
101
+ } );
102
+ return event.respondWith( claims );
103
+ }
104
+ };
105
+
106
+ rootNode.addEventListener( event.type, temp );
107
+ this[ '#' ].host.dispatchEvent( event );
108
+ rootNode.removeEventListener( event.type, temp );
86
109
  } );
87
110
  }
88
111
 
@@ -31,12 +31,17 @@ export default function() {
31
31
  Object.defineProperty( this, 'signal', { get: () => signal } );
32
32
  Object.defineProperty( this, 'diff', { get: () => diff } );
33
33
  Object.defineProperty( this, 'options', { get: () => otherOpts } );
34
+ Object.defineProperty( this, 'meta', { value: {} } );
34
35
  }
35
36
 
37
+ get target() { return super.target || this.meta.target; }
38
+ get answered() { return this.meta.answered || false; }
39
+
36
40
  /**
37
41
  * @respondWith
38
42
  */
39
43
  respondWith( response ) {
44
+ this.meta.answered = true;
40
45
  if ( this.diff ) {
41
46
  if ( '_prevValue' in this && this._prevValue === response ) return;
42
47
  Object.defineProperty( this, '_prevValue', { value: response, configurable: true } );
@@ -38,30 +38,13 @@ export default function init( $config = {} ) {
38
38
  */
39
39
  function exposeAPIs( config ) {
40
40
  const window = this;
41
- // Assertions
42
- if ( config.api.contexts in window.document ) { throw new Error( `document already has a "${ config.api.contexts }" property!` ); }
43
- if ( config.api.contexts in window.HTMLElement.prototype ) { throw new Error( `The "HTMLElement" class already has a "${ config.api.contexts }" property!` ); }
44
- // Definitions
45
- Object.defineProperty( window.document, config.api.contexts, { get: function() {
46
- return DOMContexts.instance( window.document );
47
- } } );
48
- Object.defineProperty( window.HTMLElement.prototype, config.api.contexts, { get: function() {
49
- return DOMContexts.instance( this );
50
- } } );
51
- const waitlist = new Set;
52
- window.addEventListener( 'contextrequest', event => {
53
- if ( typeof event.respondWith !== 'function' ) return;
54
- waitlist.add( event );
55
- event.respondWith();
56
- } );
57
- window.addEventListener( 'contextclaim', event => {
58
- if ( typeof event.detail !== 'object' || typeof event.detail.matchEvent !== 'function' || typeof event.respondWith !== 'function' ) return;
59
- const claims = new Set;
60
- waitlist.forEach( subscriptionEvent => {
61
- if ( !event.target.contains( subscriptionEvent.target ) || !event.detail.matchEvent( subscriptionEvent ) ) return;
62
- waitlist.delete( subscriptionEvent );
63
- claims.add( subscriptionEvent );
64
- } );
65
- event.respondWith( claims );
41
+ [ window.Document.prototype, window.Element.prototype, window.ShadowRoot.prototype ].forEach( prototype => {
42
+ // No-conflict assertions
43
+ const type = prototype === window.Document.prototype ? 'Document' : ( prototype === window.ShadowRoot.prototype ? 'ShadowRoot' : 'Element' );
44
+ if ( config.api.contexts in prototype ) { throw new Error( `The ${ type } prototype already has a "${ config.api.contexts }" API!` ); }
45
+ // Definitions
46
+ Object.defineProperty( prototype, config.api.contexts, { get: function() {
47
+ return DOMContexts.instance( this );
48
+ } } );
66
49
  } );
67
50
  }
@@ -37,14 +37,14 @@ export default function init( $config = {} ) {
37
37
  function realtime( config ) {
38
38
  const window = this, { webqit: { realdom } } = window;
39
39
  // ----------------
40
- realdom.realtime( window.document ).subtree( `(${ config.discreteBindingsSelector })`, record => {
40
+ realdom.realtime( window.document ).query( `(${ config.discreteBindingsSelector })`, record => {
41
41
  cleanup.call( this, ...record.exits );
42
42
  mountDiscreteBindings.call( this, config, ...record.entrants );
43
- }, { live: true } );
44
- realdom.realtime( window.document ).subtree( config.attrSelector, record => {
43
+ }, { live: true, subtree: 'cross-roots', timing: 'sync' } );
44
+ realdom.realtime( window.document ).query( config.attrSelector, record => {
45
45
  cleanup.call( this, ...record.exits );
46
46
  mountInlineBindings.call( this, config, ...record.entrants );
47
- }, { live: true, timing: 'sync', staticSensitivity: true } );
47
+ }, { live: true, subtree: 'cross-roots', timing: 'sync', staticSensitivity: true } );
48
48
  }
49
49
 
50
50
  function createDynamicScope( config, root ) {
@@ -39,8 +39,8 @@ export default class HTMLImportsContext extends DOMContext {
39
39
  */
40
40
  handle( event ) {
41
41
  const { window: { webqit: { Observer } } } = env;
42
- // Any existing event._controller? Abort!
43
- event._controller?.abort();
42
+ // Any existing event.meta.controller? Abort!
43
+ event.meta.controller?.abort();
44
44
 
45
45
  // Parse and translate detail
46
46
  if ( ( event.detail || '' ).trim() === '/' ) return event.respondWith( this.localModules );
@@ -48,11 +48,10 @@ export default class HTMLImportsContext extends DOMContext {
48
48
  if ( !path.length ) return event.respondWith();
49
49
  path = path.join( `/${ this.configs.HTML_IMPORTS.api.defs }/` )?.split( '/' ) || [];
50
50
 
51
-
52
51
  // We'll now fulfill request
53
52
  const options = { live: event.live, signal: event.signal, descripted: true };
54
53
  // Find a way to resolve request against two sources
55
- event._controller = Observer.reduce( this.localModules, path, Observer.get, ( result, { signal } = {} ) => {
54
+ event.meta.controller = Observer.reduce( this.localModules, path, Observer.get, ( result, { signal } = {} ) => {
56
55
  const _result = Array.isArray( result ) ? result : result.value;
57
56
  const _isValidLocalResult = Array.isArray( result ) ? result.length : result.value;
58
57
  if ( !_isValidLocalResult && this.host.isConnected === false ) return; // Subtree is being disposed
@@ -71,7 +70,7 @@ export default class HTMLImportsContext extends DOMContext {
71
70
  /**
72
71
  * @unsubscribed()
73
72
  */
74
- unsubscribed( event ) { event._controller?.abort(); }
73
+ unsubscribed( event ) { event.meta.controller?.abort(); }
75
74
 
76
75
  /**
77
76
  * @startRealtime()
@@ -135,6 +135,7 @@ export default class HTMLModule {
135
135
  // Ongoing request?
136
136
  if ( this.fetchInFlight?.src === src ) return this.fetchInFlight.request;
137
137
  this.fetchInFlight?.controller.abort();
138
+
138
139
  // The promise
139
140
  const controller = new AbortController();
140
141
  const fire = ( type, detail ) => this.host.dispatchEvent( new window.CustomEvent( type, { detail } ) );
@@ -104,7 +104,7 @@ export default function() {
104
104
  if ( !record.target.isConnected ) return;
105
105
  restore();
106
106
  }
107
- }, { subtree: true, timing: 'sync', generation: 'exits' } );
107
+ }, { subtree: 'cross-roots', timing: 'sync', generation: 'exits' } );
108
108
  priv.autoRestoreRealtime = autoRestoreRealtime;
109
109
  };
110
110
 
@@ -61,29 +61,32 @@ export function getDefs( node, autoCreate = true ) {
61
61
  */
62
62
  function exposeAPIs( config ) {
63
63
  const window = this, { webqit: { oohtml: { configs } } } = window;
64
- // Assertions
65
- if ( config.api.defs in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" class already has a "${ config.api.defs }" property!` ); }
66
- if ( config.api.def in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" class already has a "${ config.api.def }" property!` ); }
67
- if ( config.api.import in window.document ) { throw new Error( `document already has a "${ config.api.import }" property!` ); }
68
- if ( config.api.import in window.HTMLElement.prototype ) { throw new Error( `The "HTMLElement" class already has a "${ config.api.import }" property!` ); }
69
- // Definitions
70
- Object.defineProperty( window.HTMLTemplateElement.prototype, config.api.defs, { get: function() {
71
- return getDefs( this );
72
- } } );
64
+ // The "def" & "defs" properties
65
+ if ( config.api.def in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" prototype already has a "${ config.api.def }" API!` ); }
66
+ if ( config.api.defs in window.HTMLTemplateElement.prototype ) { throw new Error( `The "HTMLTemplateElement" prototype already has a "${ config.api.defs }" API!` ); }
67
+ // No-conflict assertions
73
68
  Object.defineProperty( window.HTMLTemplateElement.prototype, config.api.def, { get: function() {
74
69
  return this.getAttribute( config.attr.def );
75
70
  } } );
71
+ Object.defineProperty( window.HTMLTemplateElement.prototype, config.api.defs, { get: function() {
72
+ return getDefs( this );
73
+ } } );
74
+ // The "scoped" property
76
75
  Object.defineProperty( window.HTMLTemplateElement.prototype, 'scoped', {
77
76
  configurable: true,
78
77
  get() { return this.hasAttribute( 'scoped' ); },
79
78
  set( value ) { this.toggleAttribute( 'scoped', value ); },
80
79
  } );
81
- Object.defineProperty( window.document, config.api.import, { value: function( ref, live = false, callback = null ) {
82
- return importRequest( window.document, ...arguments );
83
- } } );
84
- Object.defineProperty( window.HTMLElement.prototype, config.api.import, { value: function( ref, live = false, callback = null ) {
85
- return importRequest( this, ...arguments );
86
- } } );
80
+ // The Import API
81
+ [ window.Document.prototype, window.Element.prototype, window.ShadowRoot.prototype ].forEach( prototype => {
82
+ // No-conflict assertions
83
+ const type = prototype === window.Document.prototype ? 'Document' : ( prototype === window.ShadowRoot.prototype ? 'ShadowRoot' : 'Element' );
84
+ if ( config.api.import in prototype ) { throw new Error( `The ${ type } prototype already has a "${ config.api.import }" API!` ); }
85
+ // Definitions
86
+ Object.defineProperty( prototype, config.api.import, { value: function( ref, live = false, callback = null ) {
87
+ return importRequest( this, ...arguments );
88
+ } });
89
+ } );
87
90
  function importRequest( context, ref, live = false, callback = null ) {
88
91
  let options = {};
89
92
  if ( typeof live === 'function' ) {
@@ -127,11 +130,11 @@ function realtime( config ) {
127
130
  }
128
131
  };
129
132
  // ------------
130
- realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( [ config.templateSelector, config.importsContextSelector ], record => {
133
+ realdom.realtime( window.document ).query( [ config.templateSelector, config.importsContextSelector ], record => {
131
134
  record.entrants.forEach( entry => {
132
135
  if ( entry.matches( config.templateSelector ) ) {
133
136
  const htmlModule = HTMLModule.instance( entry );
134
- htmlModule.ownerContext = entry.scoped ? record.target : window.document;
137
+ htmlModule.ownerContext = entry.scoped ? record.target : record.target.getRootNode();
135
138
  const ownerContextModulesObj = getDefs( htmlModule.ownerContext );
136
139
  if ( htmlModule.defId ) { Observer.set( ownerContextModulesObj, htmlModule.defId, entry ); }
137
140
  // The ownerContext's defs - ownerContextModulesObj - has to be populated
@@ -152,15 +155,15 @@ function realtime( config ) {
152
155
  detachImportsContext( entry );
153
156
  }
154
157
  } );
155
- }, { live: true, timing: 'sync', staticSensitivity: true } );
158
+ }, { live: true, subtree: 'cross-roots', timing: 'sync', staticSensitivity: true } );
156
159
 
157
160
  // ------------
158
161
  // IMPORTS
159
162
  // ------------
160
- realdom.realtime( window.document ).subtree/*instead of observe(); reason: jsdom timing*/( config.elements.import, record => {
163
+ realdom.realtime( window.document ).query( config.elements.import, record => {
161
164
  record.entrants.forEach( node => handleRealtime( node, true, record ) );
162
165
  record.exits.forEach( node => handleRealtime( node, false, record ) );
163
- }, { live: true, timing: 'sync' } );
166
+ }, { live: true, subtree: 'cross-roots', timing: 'sync' } );
164
167
  function handleRealtime( entry, connectedState ) {
165
168
  const elInstance = HTMLImportElement.instance( entry );
166
169
  if ( connectedState ) { elInstance[ '#' ].connectedCallback(); }
@@ -168,7 +171,7 @@ function realtime( config ) {
168
171
  }
169
172
  // Hydration
170
173
  if ( window.webqit.env === 'server' ) return;
171
- realdom.realtime( window.document ).subtree( `(${ config.anchorNodeSelector })`, record => {
174
+ realdom.realtime( window.document ).query( `(${ config.anchorNodeSelector })`, record => {
172
175
  record.entrants.forEach( anchorNode => {
173
176
  if ( _( anchorNode ).get( 'isAnchorNode' ) ) return; // Doubling up on the early return above! Ignoring every just created anchorNode
174
177
  const reviver = window.document.createElement( 'div' );
@@ -183,5 +186,5 @@ function realtime( config ) {
183
186
  }
184
187
  HTMLImportElement.instance( importEl )[ '#' ].hydrate( anchorNode, slottedElements );
185
188
  } );
186
- }, { live: true } );
189
+ }, { live: true, subtree: 'cross-roots', timing: 'sync' } );
187
190
  }
package/src/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @imports
3
3
  */
4
- import * as QuantumJS from `@webqit/quantum-js`;
4
+ import * as QuantumJS from '@webqit/quantum-js';
5
5
  import init from './init.js';
6
6
 
7
7
  /**
package/src/index.lite.js CHANGED
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * @imports
4
4
  */
5
- import * as QuantumJS from `@webqit/quantum-js/lite`;
5
+ import * as QuantumJS from '@webqit/quantum-js/lite';
6
6
  import init from './init.js';
7
7
 
8
8
  /**
@@ -32,8 +32,8 @@ export default class DOMNamingContext extends DOMContext {
32
32
  */
33
33
  handle( event ) {
34
34
  const { window: { webqit: { Observer } } } = env;
35
- // Any existing event._controller? Abort!
36
- event._controller?.abort();
35
+ // Any existing event.meta.controller? Abort!
36
+ event.meta.controller?.abort();
37
37
 
38
38
  // Parse and translate detail
39
39
  if ( !( event.detail || '' ).trim() ) return event.respondWith( Observer.unproxy( this.namespaceObj ) );
@@ -41,7 +41,7 @@ export default class DOMNamingContext extends DOMContext {
41
41
  if ( !path.length ) return event.respondWith();
42
42
  path = path.join( `/${ this.configs.NAMESPACED_HTML.api.namespace }/` )?.split( '/' ) || [];
43
43
 
44
- event._controller = Observer.reduce( this.namespaceObj, path, Observer.get, descriptor => {
44
+ event.meta.controller = Observer.reduce( this.namespaceObj, path, Observer.get, descriptor => {
45
45
  if ( this.disposed ) return; // If already scheduled but aborted as in provider unmounting
46
46
  event.respondWith( descriptor.value );
47
47
  }, { live: event.live, signal: event.signal, descripted: true } );
@@ -50,5 +50,5 @@ export default class DOMNamingContext extends DOMContext {
50
50
  /**
51
51
  * @unsubscribed()
52
52
  */
53
- unsubscribed( event ) { event._controller?.abort(); }
53
+ unsubscribed( event ) { event.meta.controller?.abort(); }
54
54
  }