@@ -7,13 +7,12 @@ import { Node } from '../../../interfaces';
7
7
import { globals , sanitize } from '../../../utils/names' ;
8
8
import deindent from '../../utils/deindent' ;
9
9
import Wrapper from '../../render_dom/wrappers/shared/Wrapper' ;
10
-
11
10
import TemplateScope from './TemplateScope' ;
12
11
import get_object from '../../utils/get_object' ;
13
- import { nodes_match } from '../../../utils/nodes_match' ;
14
12
import Block from '../../render_dom/Block' ;
15
13
import { INode } from '../interfaces' ;
16
14
import is_dynamic from '../../render_dom/wrappers/shared/is_dynamic' ;
15
+ import { invalidate } from '../../utils/invalidate' ;
17
16
18
17
const binary_operators : Record < string , number > = {
19
18
'**' : 15 ,
@@ -241,7 +240,6 @@ export default class Expression {
241
240
const { code } = component ;
242
241
243
242
let function_expression ;
244
- let pending_assignments : Set < string > = new Set ( ) ;
245
243
246
244
let dependencies : Set < string > ;
247
245
let contextual_dependencies : Set < string > ;
@@ -309,16 +307,6 @@ export default class Expression {
309
307
if ( map . has ( node ) ) scope = scope . parent ;
310
308
311
309
if ( node === function_expression ) {
312
- if ( pending_assignments . size > 0 ) {
313
- if ( node . type !== 'ArrowFunctionExpression' ) {
314
- // this should never happen!
315
- throw new Error ( `Well that's odd` ) ;
316
- }
317
-
318
- // TOOD optimisation — if this is an event handler,
319
- // the return value doesn't matter
320
- }
321
-
322
310
const name = component . get_unique_name (
323
311
sanitize ( get_function_name ( node , owner ) )
324
312
) ;
@@ -334,40 +322,11 @@ export default class Expression {
334
322
args . push ( original_params ) ;
335
323
}
336
324
337
- let body = code . slice ( node . body . start , node . body . end ) . trim ( ) ;
338
- if ( node . body . type !== 'BlockStatement' ) {
339
- if ( pending_assignments . size > 0 ) {
340
- const dependencies = new Set ( ) ;
341
- pending_assignments . forEach ( name => {
342
- if ( template_scope . names . has ( name ) ) {
343
- template_scope . dependencies_for_name . get ( name ) . forEach ( dependency => {
344
- dependencies . add ( dependency ) ;
345
- } ) ;
346
- } else {
347
- dependencies . add ( name ) ;
348
- }
349
- } ) ;
350
-
351
- const insert = Array . from ( dependencies ) . map ( name => component . invalidate ( name ) ) . join ( '; ' ) ;
352
- pending_assignments = new Set ( ) ;
325
+ const body = code . slice ( node . body . start , node . body . end ) . trim ( ) ;
353
326
354
- component . has_reactive_assignments = true ;
355
-
356
- body = deindent `
357
- {
358
- const $$result = ${ body } ;
359
- ${ insert } ;
360
- return $$result;
361
- }
362
- ` ;
363
- } else {
364
- body = `{\n\treturn ${ body } ;\n}` ;
365
- }
366
- }
367
-
368
- const fn = deindent `
369
- ${ node . async && 'async ' } function${ node . generator && '*' } ${ name } (${ args . join ( ', ' ) } ) ${ body }
370
- ` ;
327
+ const fn = node . type === 'FunctionExpression'
328
+ ? `${ node . async ? 'async ' : '' } function${ node . generator ? '*' : '' } ${ name } (${ args . join ( ', ' ) } ) ${ body } `
329
+ : `const ${ name } = ${ node . async ? 'async ' : '' } (${ args . join ( ', ' ) } ) => ${ body } ;` ;
371
330
372
331
if ( dependencies . size === 0 && contextual_dependencies . size === 0 ) {
373
332
// we can hoist this out of the component completely
@@ -421,66 +380,26 @@ export default class Expression {
421
380
contextual_dependencies = null ;
422
381
}
423
382
424
- if ( node . type === 'AssignmentExpression' ) {
425
- const names = node . left . type === 'MemberExpression'
426
- ? [ get_object ( node . left ) . name ]
427
- : extract_names ( node . left ) ;
383
+ if ( node . type === 'AssignmentExpression' || node . type === 'UpdateExpression' ) {
384
+ const assignee = node . type === 'AssignmentExpression' ? node . left : node . argument ;
428
385
429
- if ( node . operator === '=' && nodes_match ( node . left , node . right ) ) {
430
- const dirty = names . filter ( name => {
431
- return ! scope . declarations . has ( name ) ;
432
- } ) ;
433
-
434
- if ( dirty . length ) component . has_reactive_assignments = true ;
386
+ // normally (`a = 1`, `b.c = 2`), there'll be a single name
387
+ // (a or b). In destructuring cases (`[d, e] = [e, d]`) there
388
+ // may be more, in which case we need to tack the extra ones
389
+ // onto the initial function call
390
+ const names = new Set ( extract_names ( assignee ) ) ;
435
391
436
- code . overwrite ( node . start , node . end , dirty . map ( n => component . invalidate ( n ) ) . join ( '; ' ) ) ;
437
- } else {
438
- names . forEach ( name => {
439
- if ( scope . declarations . has ( name ) ) return ;
440
-
441
- const variable = component . var_lookup . get ( name ) ;
442
- if ( variable && variable . hoistable ) return ;
443
-
444
- pending_assignments . add ( name ) ;
445
- } ) ;
446
- }
447
- } else if ( node . type === 'UpdateExpression' ) {
448
- const { name } = get_object ( node . argument ) ;
449
-
450
- if ( scope . declarations . has ( name ) ) return ;
451
-
452
- const variable = component . var_lookup . get ( name ) ;
453
- if ( variable && variable . hoistable ) return ;
454
-
455
- pending_assignments . add ( name ) ;
456
- }
457
-
458
- if ( / S t a t e m e n t / . test ( node . type ) ) {
459
- if ( pending_assignments . size > 0 ) {
460
- const has_semi = code . original [ node . end - 1 ] === ';' ;
461
-
462
- const insert = (
463
- ( has_semi ? ' ' : '; ' ) +
464
- Array . from ( pending_assignments ) . map ( name => component . invalidate ( name ) ) . join ( '; ' )
465
- ) ;
466
-
467
- if ( / ^ ( B r e a k | C o n t i n u e | R e t u r n ) S t a t e m e n t / . test ( node . type ) ) {
468
- if ( node . argument ) {
469
- code . overwrite ( node . start , node . argument . start , `var $$result = ` ) ;
470
- code . appendLeft ( node . end , `${ insert } ; return $$result` ) ;
471
- } else {
472
- code . prependRight ( node . start , `${ insert } ; ` ) ;
473
- }
474
- } else if ( parent && / ( I f | F o r ( I n | O f ) ? | W h i l e ) S t a t e m e n t / . test ( parent . type ) && node . type !== 'BlockStatement' ) {
475
- code . prependRight ( node . start , '{ ' ) ;
476
- code . appendLeft ( node . end , `${ insert } ; }` ) ;
392
+ const traced : Set < string > = new Set ( ) ;
393
+ names . forEach ( name => {
394
+ const dependencies = template_scope . dependencies_for_name . get ( name ) ;
395
+ if ( dependencies ) {
396
+ dependencies . forEach ( name => traced . add ( name ) ) ;
477
397
} else {
478
- code . appendLeft ( node . end , ` ${ insert } ;` ) ;
398
+ traced . add ( name ) ;
479
399
}
400
+ } ) ;
480
401
481
- component . has_reactive_assignments = true ;
482
- pending_assignments = new Set ( ) ;
483
- }
402
+ invalidate ( component , scope , code , node , traced ) ;
484
403
}
485
404
}
486
405
} ) ;
0 commit comments