@webqit/oohtml 3.1.5 → 3.1.7

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.
@@ -52,7 +52,7 @@ function realtime( config ) {
52
52
  function createDynamicScope( config, root ) {
53
53
  const { webqit: { Observer, DOMBindingsContext } } = this;
54
54
  if ( _( root ).has( 'data-binding' ) ) return _( root ).get( 'data-binding' );
55
- const scope = {}, abortController = new AbortController;
55
+ const scope = Object.create( null ), abortController = new AbortController;
56
56
  Observer.intercept( scope, {
57
57
  get: ( e, recieved, next ) => {
58
58
  if ( !( e.key in scope ) ) {
@@ -76,7 +76,7 @@ function cleanup( ...entries ) {
76
76
  const { bindings, abortController } = _( root ).get( 'data-binding' ) || {};
77
77
  if ( !bindings?.has( node ) ) return;
78
78
  bindings.get( node ).state.dispose();
79
- bindings.get( node ).signals.forEach( s => s.abort() );
79
+ bindings.get( node ).signals?.forEach( s => s.abort() );
80
80
  bindings.delete( node );
81
81
  if ( !bindings.size ) {
82
82
  abortController.abort();
@@ -119,38 +119,47 @@ async function mountDiscreteBindings( config, ...entries ) {
119
119
  }, [] );
120
120
 
121
121
  for ( const { textNode, template, anchorNode } of instances ) {
122
- const { scope: env, bindings } = createDynamicScope.call( this, config, textNode.parentNode );
123
- let source = '';
124
- source += `let content = ((${ template.expr }) ?? '') + '';`;
125
- source += `this.nodeValue = content;`;
126
- if ( anchorNode ) { source += `$anchorNode__.nodeValue = "${ config.tokens.tagStart }${ escDouble( template.expr ) }${ config.tokens.stateStart }" + content.length + "${ config.tokens.stateEnd } ${ config.tokens.tagEnd }";`; }
127
- const compiled = new QuantumAsyncFunction( '$signals__', `$anchorNode__`, source, { env } );
128
- const signals = [];
129
- bindings.set( textNode, { compiled, signals, state: await compiled.call( textNode, signals, anchorNode ), } );
122
+ const compiled = compileDiscreteBindings( config, template.expr );
123
+ const { scope, bindings } = createDynamicScope.call( this, config, textNode.parentNode );
124
+ Object.defineProperty( textNode, '$oohtml_internal_databinding_anchorNode', { value: anchorNode, configurable: true } );
125
+ bindings.set( textNode, { state: await ( await compiled.bind( textNode, scope ) ).execute(), } );
130
126
  }
131
127
  }
132
128
 
129
+ const discreteParseCache = new Map;
130
+ function compileDiscreteBindings( config, str ) {
131
+ if ( discreteParseCache.has( str ) ) return discreteParseCache.get( str );
132
+ let source = `let content = ((${ str }) ?? '') + '';`;
133
+ source += `this.nodeValue = content;`;
134
+ source += `if ( this.$oohtml_internal_databinding_anchorNode ) { this.$oohtml_internal_databinding_anchorNode.nodeValue = "${ config.tokens.tagStart }${ escDouble( str ) }${ config.tokens.stateStart }" + content.length + "${ config.tokens.stateEnd } ${ config.tokens.tagEnd }"; }`;
135
+ const { webqit: { QuantumAsyncScript } } = this;
136
+ const compiled = new QuantumAsyncScript( source );
137
+ discreteParseCache.set( str, compiled );
138
+ return compiled;
139
+ }
140
+
133
141
  async function mountInlineBindings( config, ...entries ) {
134
- const { webqit: { QuantumAsyncFunction } } = this;
135
142
  for ( const node of entries ) {
136
- const source = parseInlineBindings( config, node.getAttribute( config.attr.expr ) );
137
- const { scope: env, bindings } = createDynamicScope.call( this, config, node );
138
- const compiled = new QuantumAsyncFunction( '$signals__', source, { env } );
143
+ const compiled = compileInlineBindings( config, node.getAttribute( config.attr.expr ) );
144
+ const { scope, bindings } = createDynamicScope.call( this, config, node );
139
145
  const signals = [];
140
- bindings.set( node, { compiled, signals, state: await compiled.call( node, signals ), } );
146
+ Object.defineProperty( node, '$oohtml_internal_databinding_signals', { value: signals, configurable: true } );
147
+ bindings.set( node, { signals, state: await ( await compiled.bind( node, scope ) ).execute(), } );
141
148
  }
142
149
  }
143
150
 
144
- const parseCache = new Map;
145
- function parseInlineBindings( config, str ) {
146
- if ( parseCache.has( str ) ) return parseCache.get( str );
151
+ const inlineParseCache = new Map;
152
+ function compileInlineBindings( config, str ) {
153
+ if ( inlineParseCache.has( str ) ) return inlineParseCache.get( str );
147
154
  const validation = {};
148
- const escDouble = str => str.replace(/"/g, '\\"');
149
155
  const source = splitOuter( str, ';' ).map( str => {
150
156
  const [ left, right ] = splitOuter( str, ':' ).map( x => x.trim() );
151
157
  const directive = left[ 0 ], param = left.slice( 1 ).trim();
152
158
  const arg = `(${ right })`, $arg = `(${ arg } ?? '')`;
153
- if ( directive === '&' ) return `this.style["${ escDouble( param ) }"] = ${ $arg };`;
159
+ if ( directive === '&' ) {
160
+ if ( param.startsWith( '--' ) ) return `this.style.setProperty("${ escDouble( param ) }", ${ $arg });`;
161
+ return `this.style["${ escDouble( param ) }"] = ${ $arg };`;
162
+ }
154
163
  if ( directive === '%' ) return `this.classList.toggle("${ escDouble( param ) }", !!${ arg });`;
155
164
  if ( directive === '~' ) {
156
165
  if ( param.startsWith( '?' ) ) return `this.toggleAttribute("${ escDouble( param.substring( 1 ).trim() ) }", !!${ arg });`;
@@ -174,7 +183,7 @@ function parseInlineBindings( config, str ) {
174
183
  return `
175
184
  let $iteratee__ = ${ iteratee };
176
185
  let $import__ = this.${ config.HTML_IMPORTS.context.api.import }( ${ importSpec.trim() }, true );
177
- $signals__.push( $import__ );
186
+ this.$oohtml_internal_databinding_signals?.push( $import__ );
178
187
 
179
188
  if ( $import__.value && $iteratee__ ) {
180
189
  let $existing__ = new Map;
@@ -207,8 +216,10 @@ function parseInlineBindings( config, str ) {
207
216
  }
208
217
  if ( str.trim() ) throw new Error( `Invalid binding: ${ str }.` );
209
218
  } ).join( `\n` );
210
- parseCache.set( str, source );
211
- return source;
219
+ const { webqit: { QuantumAsyncScript } } = this;
220
+ const compiled = new QuantumAsyncScript( source );
221
+ inlineParseCache.set( str, compiled );
222
+ return compiled;
212
223
  }
213
224
 
214
225
  export function splitOuter( str, delim ) {
@@ -224,4 +235,6 @@ export function splitOuter( str, delim ) {
224
235
  splits[ 0 ] += x;
225
236
  return [ quote, depth, splits ]
226
237
  }, [ null, 0, [ '' ] ] )[ 2 ].reverse();
227
- }
238
+ }
239
+
240
+ const escDouble = str => str.replace(/"/g, '\\"');
@@ -77,7 +77,7 @@ function realtime( config ) {
77
77
  const { parserParams, compilerParams, runtimeParams } = config.advanced;
78
78
  compiledScript = new ( script.type === 'module' ? QuantumModule : ( QuantumScript || QuantumAsyncScript ) )( textContent, {
79
79
  exportNamespace: `#${ script.id }`,
80
- fileName: window.document.url,
80
+ fileName:`${ window.document.url?.split( '#' )?.[ 0 ] || '' }#${ script.id }`,
81
81
  parserParams,
82
82
  compilerParams: { ...compilerParams, startStatic: !script.quantum },
83
83
  runtimeParams,