diff --git a/src/generators/Generator.js b/src/generators/Generator.js index f7ba312078..c5147c97b1 100644 --- a/src/generators/Generator.js +++ b/src/generators/Generator.js @@ -9,7 +9,7 @@ import { removeNode, removeObjectKey } from '../utils/removeNode.js'; import getIntro from './shared/utils/getIntro.js'; import getOutro from './shared/utils/getOutro.js'; import processCss from './shared/processCss.js'; -import annotateWithScopes from './annotateWithScopes.js'; +import annotateWithScopes from '../utils/annotateWithScopes.js'; const test = typeof global !== 'undefined' && global.__svelte_test; diff --git a/src/generators/dom/index.js b/src/generators/dom/index.js index 3e994e0b39..1470b39342 100644 --- a/src/generators/dom/index.js +++ b/src/generators/dom/index.js @@ -1,3 +1,8 @@ +import MagicString from 'magic-string'; +import { parse } from 'acorn'; +import annotateWithScopes from '../../utils/annotateWithScopes.js'; +import isReference from '../../utils/isReference.js'; +import { walk } from 'estree-walker'; import deindent from '../../utils/deindent.js'; import CodeBuilder from '../../utils/CodeBuilder.js'; import visit from './visit.js'; @@ -296,8 +301,36 @@ export default function dom ( parsed, source, options ) { ); } else { generator.uses.forEach( key => { - const fn = shared[ key ]; // eslint-disable-line import/namespace - builders.main.addBlock( fn.toString().replace( /^function [^(]*/, 'function ' + generator.alias( key ) ) ); + const str = shared[ key ].toString(); // eslint-disable-line import/namespace + const code = new MagicString( str ); + const fn = parse( str ).body[0]; + + let scope = annotateWithScopes( fn ); + + walk( fn, { + enter ( node, parent ) { + if ( node._scope ) scope = node._scope; + + if ( node.type === 'Identifier' && isReference( node, parent ) && !scope.has( node.name ) ) { + if ( node.name in shared ) { + // this helper function depends on another one + generator.uses.add( node.name ); + + const alias = generator.alias( node.name ); + if ( alias !== node.name ) code.overwrite( node.start, node.end, alias ); + } + } + }, + + leave ( node ) { + if ( node._scope ) scope = scope.parent; + } + }); + + const alias = generator.alias( fn.id.name ); + if ( alias !== fn.id.name ) code.overwrite( fn.id.start, fn.id.end, alias ); + + builders.main.addBlock( code.toString() ); }); } diff --git a/src/shared/index.js b/src/shared/index.js index 1ce6b42ceb..de2dee3126 100644 --- a/src/shared/index.js +++ b/src/shared/index.js @@ -23,18 +23,18 @@ export function dispatchObservers ( component, group, newState, oldState ) { var newValue = newState[ key ]; var oldValue = oldState[ key ]; - if ( newValue === oldValue && typeof newValue !== 'object' ) continue; - - var callbacks = group[ key ]; - if ( !callbacks ) continue; - - for ( var i = 0; i < callbacks.length; i += 1 ) { - var callback = callbacks[i]; - if ( callback.__calling ) continue; - - callback.__calling = true; - callback.call( component, newValue, oldValue ); - callback.__calling = false; + if ( differs( newValue, oldValue ) ) { + var callbacks = group[ key ]; + if ( !callbacks ) continue; + + for ( var i = 0; i < callbacks.length; i += 1 ) { + var callback = callbacks[i]; + if ( callback.__calling ) continue; + + callback.__calling = true; + callback.call( component, newValue, oldValue ); + callback.__calling = false; + } } } } diff --git a/src/shared/methods.js b/src/shared/methods.js index 2db30991ea..d589184bd8 100644 --- a/src/shared/methods.js +++ b/src/shared/methods.js @@ -39,22 +39,7 @@ export function observeDev ( key, callback, options ) { throw new Error( message ); } - var group = ( options && options.defer ) ? this._observers.pre : this._observers.post; - - ( group[ key ] || ( group[ key ] = [] ) ).push( callback ); - - if ( !options || options.init !== false ) { - callback.__calling = true; - callback.call( this, this._state[ key ] ); - callback.__calling = false; - } - - return { - cancel: function () { - var index = group[ key ].indexOf( callback ); - if ( ~index ) group[ key ].splice( index, 1 ); - } - }; + return observe.call( this, key, callback, options ); } export function on ( eventName, handler ) { @@ -77,15 +62,7 @@ export function onDev ( eventName, handler ) { return this.on( 'destroy', handler ); } - var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] ); - handlers.push( handler ); - - return { - cancel: function () { - var index = handlers.indexOf( handler ); - if ( ~index ) handlers.splice( index, 1 ); - } - }; + return on.call( this, eventName, handler ); } export function set ( newState ) { diff --git a/src/generators/annotateWithScopes.js b/src/utils/annotateWithScopes.js similarity index 100% rename from src/generators/annotateWithScopes.js rename to src/utils/annotateWithScopes.js