leaner 0.1.4 → 0.3.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/dist/core.js +25 -3
- package/dist/web.js +318 -60
- package/package.json +1 -1
- package/types/core.d.ts +1 -1
package/dist/core.js
CHANGED
|
@@ -92,6 +92,9 @@ function withScope( scope, callback ) {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
function createWatcher( deps, callback, async ) {
|
|
95
|
+
if ( async )
|
|
96
|
+
callback = createSafeCallback( callback );
|
|
97
|
+
|
|
95
98
|
const watcher = {
|
|
96
99
|
deps,
|
|
97
100
|
callback,
|
|
@@ -99,7 +102,7 @@ function createWatcher( deps, callback, async ) {
|
|
|
99
102
|
};
|
|
100
103
|
|
|
101
104
|
if ( current != null )
|
|
102
|
-
current.push( watcher );
|
|
105
|
+
current.watchers.push( watcher );
|
|
103
106
|
|
|
104
107
|
if ( deps != null ) {
|
|
105
108
|
for ( const dep of deps ) {
|
|
@@ -110,6 +113,24 @@ function createWatcher( deps, callback, async ) {
|
|
|
110
113
|
return watcher;
|
|
111
114
|
}
|
|
112
115
|
|
|
116
|
+
function createSafeCallback( callback ) {
|
|
117
|
+
if ( current != null && current.errorHandler != null ) {
|
|
118
|
+
const handler = current.errorHandler;
|
|
119
|
+
|
|
120
|
+
return safeCallback;
|
|
121
|
+
|
|
122
|
+
function safeCallback() {
|
|
123
|
+
try {
|
|
124
|
+
callback();
|
|
125
|
+
} catch ( err ) {
|
|
126
|
+
handler( err );
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return callback;
|
|
132
|
+
}
|
|
133
|
+
|
|
113
134
|
function updateWatcher( watcher, deps ) {
|
|
114
135
|
for ( const dep of deps ) {
|
|
115
136
|
dep.add( watcher );
|
|
@@ -126,7 +147,7 @@ function updateWatcher( watcher, deps ) {
|
|
|
126
147
|
}
|
|
127
148
|
|
|
128
149
|
function destroyScope( scope ) {
|
|
129
|
-
for ( const watcher of scope ) {
|
|
150
|
+
for ( const watcher of scope.watchers ) {
|
|
130
151
|
watcher.callback = null;
|
|
131
152
|
|
|
132
153
|
if ( watcher.deps != null ) {
|
|
@@ -540,8 +561,9 @@ function watch( getter, callback ) {
|
|
|
540
561
|
updateWatcher( watcher, newDeps );
|
|
541
562
|
|
|
542
563
|
if ( newValue !== value ) {
|
|
543
|
-
|
|
564
|
+
const oldValue = value;
|
|
544
565
|
value = newValue;
|
|
566
|
+
callback( newValue, oldValue );
|
|
545
567
|
}
|
|
546
568
|
}
|
|
547
569
|
}
|
package/dist/web.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { withScope, destroyScope, reactive, constant } from 'leaner';
|
|
1
|
+
import { withScope, destroyScope, reactive, constant, state } from 'leaner';
|
|
2
2
|
|
|
3
3
|
function appendToArray( item, target ) {
|
|
4
4
|
if ( Array.isArray( item ) )
|
|
@@ -37,15 +37,21 @@ function createComponent( template ) {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
function createContext( parent ) {
|
|
40
|
-
|
|
40
|
+
const context = {
|
|
41
41
|
parent,
|
|
42
42
|
children: null,
|
|
43
|
-
scope:
|
|
43
|
+
scope: {
|
|
44
|
+
watchers: [],
|
|
45
|
+
errorHandler: err => handleError( context, err ),
|
|
46
|
+
},
|
|
44
47
|
mount: null,
|
|
45
48
|
destroy: null,
|
|
46
49
|
refs: null,
|
|
47
50
|
services: null,
|
|
51
|
+
errorHandler: null,
|
|
48
52
|
};
|
|
53
|
+
|
|
54
|
+
return context;
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
function createChildContext() {
|
|
@@ -111,40 +117,63 @@ function mountContext( context ) {
|
|
|
111
117
|
mountContext( child );
|
|
112
118
|
}
|
|
113
119
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
120
|
+
withContext( context, () => {
|
|
121
|
+
if ( context.refs != null ) {
|
|
122
|
+
for ( const ref of context.refs )
|
|
123
|
+
ref.callback( ref.element );
|
|
124
|
+
}
|
|
118
125
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
if ( context.mount != null ) {
|
|
127
|
+
for ( const callback of context.mount )
|
|
128
|
+
callback();
|
|
129
|
+
}
|
|
130
|
+
} );
|
|
123
131
|
}
|
|
124
132
|
|
|
125
133
|
function destroyContext( context ) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
callback
|
|
129
|
-
|
|
130
|
-
|
|
134
|
+
withContext( context, () => {
|
|
135
|
+
if ( context.destroy != null ) {
|
|
136
|
+
for ( const callback of context.destroy )
|
|
137
|
+
callback();
|
|
138
|
+
context.destroy = null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if ( context.refs != null ) {
|
|
142
|
+
for ( const ref of context.refs )
|
|
143
|
+
ref.callback( null );
|
|
144
|
+
context.refs = null;
|
|
145
|
+
}
|
|
146
|
+
} );
|
|
131
147
|
|
|
132
148
|
context.mount = null;
|
|
133
149
|
|
|
134
|
-
if ( context.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
context.refs = null;
|
|
150
|
+
if ( context.scope.watchers.length > 0 ) {
|
|
151
|
+
destroyScope( context.scope );
|
|
152
|
+
context.scope.watchers = [];
|
|
138
153
|
}
|
|
139
154
|
|
|
140
|
-
if ( context.
|
|
155
|
+
if ( context.children != null ) {
|
|
156
|
+
for ( const child of context.children )
|
|
157
|
+
destroyContext( child );
|
|
158
|
+
context.children = null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
context.services = null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function cleanUpContext( context ) {
|
|
165
|
+
context.destroy = null;
|
|
166
|
+
context.refs = null;
|
|
167
|
+
context.mount = null;
|
|
168
|
+
|
|
169
|
+
if ( context.scope.watchers.length > 0 ) {
|
|
141
170
|
destroyScope( context.scope );
|
|
142
|
-
context.scope = [];
|
|
171
|
+
context.scope.watchers = [];
|
|
143
172
|
}
|
|
144
173
|
|
|
145
174
|
if ( context.children != null ) {
|
|
146
175
|
for ( const child of context.children )
|
|
147
|
-
|
|
176
|
+
cleanUpContext( child );
|
|
148
177
|
context.children = null;
|
|
149
178
|
}
|
|
150
179
|
|
|
@@ -162,12 +191,44 @@ function provide( key, value ) {
|
|
|
162
191
|
}
|
|
163
192
|
|
|
164
193
|
function inject( key ) {
|
|
194
|
+
if ( current == null )
|
|
195
|
+
throw new Error( 'inject() cannot be called outside of a component' );
|
|
196
|
+
|
|
165
197
|
for ( let context = current; context != null; context = context.parent ) {
|
|
166
198
|
if ( context.services != null && context.services.has( key ) )
|
|
167
199
|
return context.services.get( key );
|
|
168
200
|
}
|
|
169
201
|
}
|
|
170
202
|
|
|
203
|
+
function handleError( context, err ) {
|
|
204
|
+
while ( context != null) {
|
|
205
|
+
if ( context.errorHandler != null ) {
|
|
206
|
+
context.errorHandler( err );
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
context = context.parent;
|
|
210
|
+
}
|
|
211
|
+
throw err;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function createSafeHandler( callback ) {
|
|
215
|
+
if ( current != null ) {
|
|
216
|
+
const context = current;
|
|
217
|
+
|
|
218
|
+
return safeHandler;
|
|
219
|
+
|
|
220
|
+
function safeHandler( e ) {
|
|
221
|
+
try {
|
|
222
|
+
callback( e );
|
|
223
|
+
} catch ( err ) {
|
|
224
|
+
handleError( context, err );
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return callback;
|
|
230
|
+
}
|
|
231
|
+
|
|
171
232
|
function setClasses( element, classes ) {
|
|
172
233
|
if ( typeof classes == 'function' ) {
|
|
173
234
|
reactive( classes, value => {
|
|
@@ -295,12 +356,18 @@ function removeNode( node ) {
|
|
|
295
356
|
}
|
|
296
357
|
|
|
297
358
|
function replaceNode( newNode, node ) {
|
|
359
|
+
// this is safe because the parent of a DynamicNode is always a true DOM node
|
|
360
|
+
const parent = Array.isArray( node ) ? node[ 0 ].parentNode : node.parentNode;
|
|
361
|
+
|
|
362
|
+
// remember the value of a <select> element so that it can be restored later
|
|
363
|
+
const currentValue = parent instanceof HTMLSelectElement ? parent.value : null;
|
|
364
|
+
|
|
298
365
|
if ( newNode instanceof Node && node instanceof Node ) {
|
|
299
|
-
|
|
366
|
+
parent.replaceChild( newNode, node );
|
|
300
367
|
} else if ( Array.isArray( newNode ) && Array.isArray( node ) ) {
|
|
301
368
|
let newStart = 0, start = 0;
|
|
302
369
|
let newEnd = newNode.length, end = node.length;
|
|
303
|
-
let
|
|
370
|
+
let before;
|
|
304
371
|
|
|
305
372
|
while ( newStart < newEnd || start < end ) {
|
|
306
373
|
// skip equal nodes at the start
|
|
@@ -324,13 +391,15 @@ function replaceNode( newNode, node ) {
|
|
|
324
391
|
before = node[ start ];
|
|
325
392
|
if ( before instanceof DynamicNode )
|
|
326
393
|
before = findFirstChild( before.content );
|
|
327
|
-
|
|
328
|
-
} else {
|
|
394
|
+
} else if ( newStart > 0 ) {
|
|
329
395
|
let after = newNode[ newStart - 1 ];
|
|
330
396
|
if ( after instanceof DynamicNode )
|
|
331
397
|
after = findLastChild( after.content );
|
|
332
398
|
before = after.nextSibling;
|
|
333
|
-
|
|
399
|
+
} else {
|
|
400
|
+
before = newNode[ newEnd ];
|
|
401
|
+
if ( before instanceof DynamicNode )
|
|
402
|
+
before = findFirstChild( before.content );
|
|
334
403
|
}
|
|
335
404
|
}
|
|
336
405
|
insertBefore( newNode[ newStart ], parent, before );
|
|
@@ -352,7 +421,6 @@ function replaceNode( newNode, node ) {
|
|
|
352
421
|
before = node[ start ];
|
|
353
422
|
if ( before instanceof DynamicNode )
|
|
354
423
|
before = findFirstChild( before.content );
|
|
355
|
-
parent = before.parentNode;
|
|
356
424
|
}
|
|
357
425
|
insertBefore( node[ end - 1 ], parent, before );
|
|
358
426
|
|
|
@@ -375,10 +443,12 @@ function replaceNode( newNode, node ) {
|
|
|
375
443
|
} else {
|
|
376
444
|
const after = findLastChild( node );
|
|
377
445
|
const before = after.nextSibling;
|
|
378
|
-
const parent = after.parentNode;
|
|
379
446
|
removeNode( node );
|
|
380
447
|
insertBefore( newNode, parent, before );
|
|
381
448
|
}
|
|
449
|
+
|
|
450
|
+
if ( currentValue != null )
|
|
451
|
+
parent.value = currentValue;
|
|
382
452
|
}
|
|
383
453
|
|
|
384
454
|
function findFirstChild( node ) {
|
|
@@ -471,12 +541,16 @@ function createForDirective( template ) {
|
|
|
471
541
|
throw new TypeError( 'Invalid for template' );
|
|
472
542
|
|
|
473
543
|
const itemsGetter = template[ 1 ];
|
|
544
|
+
const callback = template[ 2 ];
|
|
545
|
+
const useIndexes = callback.length > 1;
|
|
474
546
|
|
|
475
547
|
let length = 0;
|
|
476
548
|
let items = null;
|
|
477
549
|
|
|
478
550
|
let watchingContent = false;
|
|
479
551
|
|
|
552
|
+
let indexStates = null;
|
|
553
|
+
|
|
480
554
|
const result = new DynamicNode( null );
|
|
481
555
|
|
|
482
556
|
const context = createChildContext();
|
|
@@ -516,6 +590,8 @@ function createForDirective( template ) {
|
|
|
516
590
|
oldIndexMap.set( items[ i ], i );
|
|
517
591
|
}
|
|
518
592
|
|
|
593
|
+
let newIndexStates = null;
|
|
594
|
+
|
|
519
595
|
for ( let index = 0; index < newItems.length; index++ ) {
|
|
520
596
|
const value = newItems[ index ];
|
|
521
597
|
|
|
@@ -545,6 +621,16 @@ function createForDirective( template ) {
|
|
|
545
621
|
|
|
546
622
|
if ( oldItemContexts != null )
|
|
547
623
|
oldItemContexts.delete( itemContext );
|
|
624
|
+
|
|
625
|
+
if ( useIndexes && isMatchedByValue ) {
|
|
626
|
+
// update the index passed to the child if it's reordered
|
|
627
|
+
const indexState = indexStates.get( oldIndex );
|
|
628
|
+
if ( oldIndex != index )
|
|
629
|
+
indexState[ 1 ]( index );
|
|
630
|
+
if ( newIndexStates == null )
|
|
631
|
+
newIndexStates = new Map();
|
|
632
|
+
newIndexStates.set( index, indexState );
|
|
633
|
+
}
|
|
548
634
|
} else {
|
|
549
635
|
const itemContext = createContext( context );
|
|
550
636
|
itemContexts.push( itemContext );
|
|
@@ -555,7 +641,26 @@ function createForDirective( template ) {
|
|
|
555
641
|
|
|
556
642
|
const item = isMatchedByValue ? constant( value ) : itemsGetter[ index ];
|
|
557
643
|
|
|
558
|
-
|
|
644
|
+
let itemTemplate;
|
|
645
|
+
|
|
646
|
+
if ( useIndexes ) {
|
|
647
|
+
let indexGetter;
|
|
648
|
+
|
|
649
|
+
if ( isMatchedByValue ) {
|
|
650
|
+
// index can change in the future - use reactive state
|
|
651
|
+
const indexState = state( index );
|
|
652
|
+
if ( newIndexStates == null )
|
|
653
|
+
newIndexStates = new Map();
|
|
654
|
+
newIndexStates.set( index, indexState );
|
|
655
|
+
indexGetter = indexState[ 0 ];
|
|
656
|
+
} else {
|
|
657
|
+
indexGetter = constant( index );
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
itemTemplate = callback( item, indexGetter );
|
|
661
|
+
} else {
|
|
662
|
+
itemTemplate = callback( item );
|
|
663
|
+
}
|
|
559
664
|
|
|
560
665
|
const node = withContext( itemContext, () => make( itemTemplate ) );
|
|
561
666
|
|
|
@@ -588,9 +693,11 @@ function createForDirective( template ) {
|
|
|
588
693
|
else
|
|
589
694
|
context.children = null;
|
|
590
695
|
|
|
696
|
+
indexStates = newIndexStates;
|
|
697
|
+
|
|
591
698
|
if ( containsMatchedByValue && !watchingContent ) {
|
|
592
699
|
destroyScope( context.scope );
|
|
593
|
-
context.scope = [];
|
|
700
|
+
context.scope.watchers = [];
|
|
594
701
|
withScope( context.scope, () => {
|
|
595
702
|
// clone the array to watch all elements
|
|
596
703
|
reactive( () => [ ...itemsGetter() ], updateContent );
|
|
@@ -601,20 +708,8 @@ function createForDirective( template ) {
|
|
|
601
708
|
}
|
|
602
709
|
|
|
603
710
|
function createIfDirective( template ) {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
for ( let i = 1; i < template.length; i += 2 ) {
|
|
608
|
-
if ( i == template.length - 1 )
|
|
609
|
-
hasElse = true;
|
|
610
|
-
else if ( typeof template[ i ] == 'function' )
|
|
611
|
-
numberOfConditions++;
|
|
612
|
-
else
|
|
613
|
-
throw new TypeError( 'Invalid if template' );
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
if ( numberOfConditions == 0 )
|
|
617
|
-
throw new TypeError( 'Invalid if template' );
|
|
711
|
+
if ( template.length < 2 || typeof template[ 1 ] != 'function' )
|
|
712
|
+
throw new TypeError( 'Invalid if template' );
|
|
618
713
|
|
|
619
714
|
const result = new DynamicNode( null );
|
|
620
715
|
|
|
@@ -625,23 +720,88 @@ function createIfDirective( template ) {
|
|
|
625
720
|
return result;
|
|
626
721
|
|
|
627
722
|
function watchState() {
|
|
628
|
-
|
|
723
|
+
return template[ 1 ]();
|
|
724
|
+
}
|
|
629
725
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
726
|
+
function update( state ) {
|
|
727
|
+
let childTemplate = null;
|
|
728
|
+
if ( state ) {
|
|
729
|
+
if ( template.length == 3 )
|
|
730
|
+
childTemplate = template[ 2 ];
|
|
731
|
+
else
|
|
732
|
+
childTemplate = [ template.slice( 2 ) ];
|
|
635
733
|
}
|
|
734
|
+
updateDynamicNode( result, context, childTemplate );
|
|
735
|
+
}
|
|
736
|
+
}
|
|
636
737
|
|
|
637
|
-
|
|
638
|
-
|
|
738
|
+
function createRepeatDirective( template ) {
|
|
739
|
+
if ( template.length != 3 || typeof template[ 2 ] != 'function' )
|
|
740
|
+
throw new TypeError( 'Invalid repeat template' );
|
|
639
741
|
|
|
640
|
-
|
|
742
|
+
let count = 0;
|
|
743
|
+
|
|
744
|
+
const result = new DynamicNode( null );
|
|
745
|
+
|
|
746
|
+
const context = createChildContext();
|
|
747
|
+
|
|
748
|
+
if ( typeof template[ 1 ] == 'function' ) {
|
|
749
|
+
withScope( context.scope, () => {
|
|
750
|
+
reactive( template[ 1 ], updateCount );
|
|
751
|
+
} );
|
|
752
|
+
} else {
|
|
753
|
+
updateCount( template[ 1 ] );
|
|
641
754
|
}
|
|
642
755
|
|
|
643
|
-
|
|
644
|
-
|
|
756
|
+
return result;
|
|
757
|
+
|
|
758
|
+
function updateCount( newCount ) {
|
|
759
|
+
if ( newCount > count ) {
|
|
760
|
+
const nodes = result.content != null ? result.content.slice( 0, count ) : [];
|
|
761
|
+
const contexts = context.children != null ? context.children.slice( 0, count ) : [];
|
|
762
|
+
|
|
763
|
+
for ( let i = count; i < newCount; i++ ) {
|
|
764
|
+
const itemContext = createContext( context );
|
|
765
|
+
contexts.push( itemContext );
|
|
766
|
+
|
|
767
|
+
const itemTemplate = template[ 2 ]( i );
|
|
768
|
+
|
|
769
|
+
const node = withContext( itemContext, () => make( itemTemplate ) );
|
|
770
|
+
|
|
771
|
+
if ( Array.isArray( node ) )
|
|
772
|
+
nodes.push( new DynamicNode( node ) );
|
|
773
|
+
else
|
|
774
|
+
nodes.push( node );
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
if ( result.content != null ) {
|
|
778
|
+
replaceNode( nodes, result.content );
|
|
779
|
+
|
|
780
|
+
for ( let i = count; i < newCount; i++ )
|
|
781
|
+
mountContext( contexts[ i ] );
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
result.content = nodes;
|
|
785
|
+
context.children = contexts;
|
|
786
|
+
} else {
|
|
787
|
+
for ( let i = newCount; i < count; i++ )
|
|
788
|
+
destroyContext( context.children[ i ] );
|
|
789
|
+
|
|
790
|
+
const nodes = result.content != null ? result.content.slice( 0, newCount ) : [];
|
|
791
|
+
ensureNotEmpty( nodes );
|
|
792
|
+
|
|
793
|
+
if ( result.content != null )
|
|
794
|
+
replaceNode( nodes, result.content );
|
|
795
|
+
|
|
796
|
+
result.content = nodes;
|
|
797
|
+
|
|
798
|
+
if ( newCount == 0 )
|
|
799
|
+
context.children = null;
|
|
800
|
+
else if ( context.children != null )
|
|
801
|
+
context.children = context.children.slice( 0, newCount );
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
count = newCount;
|
|
645
805
|
}
|
|
646
806
|
}
|
|
647
807
|
|
|
@@ -683,10 +843,104 @@ function setStyleProperty( element, key, value ) {
|
|
|
683
843
|
element.style[ key ] = value;
|
|
684
844
|
}
|
|
685
845
|
|
|
846
|
+
function createSwitchDirective( template ) {
|
|
847
|
+
let numberOfConditions = 0;
|
|
848
|
+
let hasElse = false;
|
|
849
|
+
|
|
850
|
+
for ( let i = 1; i < template.length; i++ ) {
|
|
851
|
+
const condition = template[ i ];
|
|
852
|
+
if ( Array.isArray( condition ) && condition.length > 1 && condition[ 0 ] === 'if' && typeof condition[ 1 ] == 'function' )
|
|
853
|
+
numberOfConditions++;
|
|
854
|
+
else if ( i == template.length - 1 && Array.isArray( condition ) && condition.length > 0 && condition[ 0 ] === 'else' )
|
|
855
|
+
hasElse = true;
|
|
856
|
+
else
|
|
857
|
+
throw new TypeError( 'Invalid switch template' );
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
if ( numberOfConditions == 0 )
|
|
861
|
+
throw new TypeError( 'Invalid switch template' );
|
|
862
|
+
|
|
863
|
+
const result = new DynamicNode( null );
|
|
864
|
+
|
|
865
|
+
const context = createChildContext();
|
|
866
|
+
|
|
867
|
+
reactive( watchState, update );
|
|
868
|
+
|
|
869
|
+
return result;
|
|
870
|
+
|
|
871
|
+
function watchState() {
|
|
872
|
+
let state = null;
|
|
873
|
+
|
|
874
|
+
for ( let i = 0; i < numberOfConditions; i++ ) {
|
|
875
|
+
if ( template[ i + 1 ][ 1 ]() ) {
|
|
876
|
+
state = i + 1;
|
|
877
|
+
break;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
if ( state == null && hasElse )
|
|
882
|
+
state = template.length - 1;
|
|
883
|
+
|
|
884
|
+
return state;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
function update( state ) {
|
|
888
|
+
let childTemplate = null;
|
|
889
|
+
if ( state != null ) {
|
|
890
|
+
const condition = template[ state ];
|
|
891
|
+
const index = condition[ 0 ] == 'else' ? 1 : 2;
|
|
892
|
+
if ( condition.length == index + 1 )
|
|
893
|
+
childTemplate = condition[ index ];
|
|
894
|
+
else
|
|
895
|
+
childTemplate = [ condition.slice( index ) ];
|
|
896
|
+
}
|
|
897
|
+
updateDynamicNode( result, context, childTemplate );
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
function createTryDirective( template ) {
|
|
902
|
+
if ( template.length != 3 || typeof template[ 2 ] != 'function' )
|
|
903
|
+
throw new TypeError( 'Invalid try template' );
|
|
904
|
+
|
|
905
|
+
const result = new DynamicNode( null );
|
|
906
|
+
|
|
907
|
+
const context = createChildContext();
|
|
908
|
+
|
|
909
|
+
try {
|
|
910
|
+
updateDynamicNode( result, context, template[ 1 ] );
|
|
911
|
+
} catch ( err ) {
|
|
912
|
+
updateErrorState( err );
|
|
913
|
+
return result;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
context.errorHandler = asyncErrorHandler;
|
|
917
|
+
|
|
918
|
+
return result;
|
|
919
|
+
|
|
920
|
+
function asyncErrorHandler( err ) {
|
|
921
|
+
try {
|
|
922
|
+
updateErrorState( err );
|
|
923
|
+
} catch ( err ) {
|
|
924
|
+
handleError( context, err );
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
function updateErrorState( err ) {
|
|
929
|
+
context.errorHandler = null;
|
|
930
|
+
if ( result.content == null )
|
|
931
|
+
cleanUpContext( context );
|
|
932
|
+
updateDynamicNode( result, context, template[ 2 ]( err ) );
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
|
|
686
936
|
const Directives = {
|
|
687
|
-
if: createIfDirective,
|
|
688
|
-
for: createForDirective,
|
|
689
937
|
dynamic: createDynamicDirective,
|
|
938
|
+
else: unexpectedDirective,
|
|
939
|
+
for: createForDirective,
|
|
940
|
+
if: createIfDirective,
|
|
941
|
+
repeat: createRepeatDirective,
|
|
942
|
+
switch: createSwitchDirective,
|
|
943
|
+
try: createTryDirective,
|
|
690
944
|
};
|
|
691
945
|
|
|
692
946
|
const Properties = new Set( [ 'value', 'checked', 'textContent', 'innerHTML' ] );
|
|
@@ -779,7 +1033,7 @@ function setElementProperties( element, properties ) {
|
|
|
779
1033
|
|
|
780
1034
|
function setElementProperty( element, key, value ) {
|
|
781
1035
|
if ( key.startsWith( 'on' ) ) {
|
|
782
|
-
element.addEventListener( key.substring( 2 ), value );
|
|
1036
|
+
element.addEventListener( key.substring( 2 ), createSafeHandler( value ) );
|
|
783
1037
|
} else if ( Properties.has( key ) ) {
|
|
784
1038
|
if ( typeof value == 'function' )
|
|
785
1039
|
reactive( value, value => element[ key ] = value != null ? value : '' );
|
|
@@ -807,6 +1061,10 @@ function setElementAttribute( element, name, value ) {
|
|
|
807
1061
|
}
|
|
808
1062
|
}
|
|
809
1063
|
|
|
1064
|
+
function unexpectedDirective( template ) {
|
|
1065
|
+
throw new TypeError( `Unexpected ${template[ 0 ]} directive` );
|
|
1066
|
+
}
|
|
1067
|
+
|
|
810
1068
|
function createApp( component ) {
|
|
811
1069
|
const context = createContext( null );
|
|
812
1070
|
|
package/package.json
CHANGED
package/types/core.d.ts
CHANGED