From 34170a5e761423534c20a7364ccb92e3b7a4931a Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 27 May 2017 09:52:33 -0400 Subject: [PATCH 1/2] compare bundled output with expectations --- test/js/index.js | 21 + .../_actual-bundle.js | 256 +++++++++++ .../expected-bundle.js | 256 +++++++++++ .../computed-collapsed-if/_actual-bundle.js | 218 +++++++++ .../computed-collapsed-if/expected-bundle.js | 218 +++++++++ .../_actual-bundle.js | 341 +++++++++++++++ .../expected-bundle.js | 341 +++++++++++++++ .../event-handlers-custom/_actual-bundle.js | 248 +++++++++++ .../event-handlers-custom/expected-bundle.js | 248 +++++++++++ .../if-block-no-update/_actual-bundle.js | 282 ++++++++++++ .../if-block-no-update/expected-bundle.js | 282 ++++++++++++ .../samples/if-block-simple/_actual-bundle.js | 263 +++++++++++ .../if-block-simple/expected-bundle.js | 263 +++++++++++ .../non-imported-component/_actual-bundle.js | 244 +++++++++++ .../non-imported-component/expected-bundle.js | 244 +++++++++++ .../non-imported-component/expected.js | 2 +- .../samples/non-imported-component/input.html | 2 +- .../_actual-bundle.js | 215 +++++++++ .../expected-bundle.js | 215 +++++++++ .../use-elements-as-anchors/_actual-bundle.js | 414 ++++++++++++++++++ .../expected-bundle.js | 414 ++++++++++++++++++ 21 files changed, 4985 insertions(+), 2 deletions(-) create mode 100644 test/js/samples/collapses-text-around-comments/_actual-bundle.js create mode 100644 test/js/samples/collapses-text-around-comments/expected-bundle.js create mode 100644 test/js/samples/computed-collapsed-if/_actual-bundle.js create mode 100644 test/js/samples/computed-collapsed-if/expected-bundle.js create mode 100644 test/js/samples/each-block-changed-check/_actual-bundle.js create mode 100644 test/js/samples/each-block-changed-check/expected-bundle.js create mode 100644 test/js/samples/event-handlers-custom/_actual-bundle.js create mode 100644 test/js/samples/event-handlers-custom/expected-bundle.js create mode 100644 test/js/samples/if-block-no-update/_actual-bundle.js create mode 100644 test/js/samples/if-block-no-update/expected-bundle.js create mode 100644 test/js/samples/if-block-simple/_actual-bundle.js create mode 100644 test/js/samples/if-block-simple/expected-bundle.js create mode 100644 test/js/samples/non-imported-component/_actual-bundle.js create mode 100644 test/js/samples/non-imported-component/expected-bundle.js create mode 100644 test/js/samples/onrender-onteardown-rewritten/_actual-bundle.js create mode 100644 test/js/samples/onrender-onteardown-rewritten/expected-bundle.js create mode 100644 test/js/samples/use-elements-as-anchors/_actual-bundle.js create mode 100644 test/js/samples/use-elements-as-anchors/expected-bundle.js diff --git a/test/js/index.js b/test/js/index.js index bd3e9cbc6d4e..34b0c5bb69de 100644 --- a/test/js/index.js +++ b/test/js/index.js @@ -1,6 +1,7 @@ import assert from 'assert'; import * as fs from 'fs'; import * as path from 'path'; +import { rollup } from 'rollup'; import { svelte } from '../helpers.js'; describe( 'js', () => { @@ -31,11 +32,31 @@ describe( 'js', () => { fs.writeFileSync( `${dir}/_actual.js`, actual ); const expected = fs.readFileSync( `${dir}/expected.js`, 'utf-8' ); + const expectedBundle = fs.readFileSync( `${dir}/expected-bundle.js`, 'utf-8' ); assert.equal( actual.trim().replace( /^\s+$/gm, '' ), expected.trim().replace( /^\s+$/gm, '' ) ); + + return rollup({ + entry: `${dir}/_actual.js`, + plugins: [{ + resolveId ( importee, importer ) { + if ( !importer ) return importee; + if ( importee === 'svelte/shared.js' ) return path.resolve('shared.js'); + return null; + } + }] + }).then(bundle => { + const actualBundle = bundle.generate({ format: 'es' }).code; + fs.writeFileSync( `${dir}/_actual-bundle.js`, actualBundle ); + + assert.equal( + actualBundle.trim().replace( /^\s+$/gm, '' ), + expectedBundle.trim().replace( /^\s+$/gm, '' ) + ); + }); }); }); }); diff --git a/test/js/samples/collapses-text-around-comments/_actual-bundle.js b/test/js/samples/collapses-text-around-comments/_actual-bundle.js new file mode 100644 index 000000000000..c95fe9b5f137 --- /dev/null +++ b/test/js/samples/collapses-text-around-comments/_actual-bundle.js @@ -0,0 +1,256 @@ +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function appendNode ( node, target ) { + target.appendChild( node ); +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function createElement ( name ) { + return document.createElement( name ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +function setAttribute ( node, attribute, value ) { + node.setAttribute( attribute, value ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +var template = (function () { + return { + data: function () { + return { foo: 42 } + } + }; +}()); + +function add_css () { + var style = createElement( 'style' ); + style.id = "svelte-3842350206-style"; + style.textContent = "\n\tp[svelte-3842350206], [svelte-3842350206] p {\n\t\tcolor: red;\n\t}\n"; + appendNode( style, document.head ); +} + +function create_main_fragment ( state, component ) { + var text_value; + + var p = createElement( 'p' ); + setAttribute( p, 'svelte-3842350206', '' ); + var text = createText( text_value = state.foo ); + appendNode( text, p ); + + return { + mount: function ( target, anchor ) { + insertNode( p, target, anchor ); + }, + + update: function ( changed, state ) { + if ( text_value !== ( text_value = state.foo ) ) { + text.data = text_value; + } + }, + + destroy: function ( detach ) { + if ( detach ) { + detachNode( p ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = assign( template.data(), options.data ); + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + if ( !document.getElementById( "svelte-3842350206-style" ) ) add_css(); + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + this._fragment.update( newState, this._state ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/collapses-text-around-comments/expected-bundle.js b/test/js/samples/collapses-text-around-comments/expected-bundle.js new file mode 100644 index 000000000000..c95fe9b5f137 --- /dev/null +++ b/test/js/samples/collapses-text-around-comments/expected-bundle.js @@ -0,0 +1,256 @@ +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function appendNode ( node, target ) { + target.appendChild( node ); +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function createElement ( name ) { + return document.createElement( name ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +function setAttribute ( node, attribute, value ) { + node.setAttribute( attribute, value ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +var template = (function () { + return { + data: function () { + return { foo: 42 } + } + }; +}()); + +function add_css () { + var style = createElement( 'style' ); + style.id = "svelte-3842350206-style"; + style.textContent = "\n\tp[svelte-3842350206], [svelte-3842350206] p {\n\t\tcolor: red;\n\t}\n"; + appendNode( style, document.head ); +} + +function create_main_fragment ( state, component ) { + var text_value; + + var p = createElement( 'p' ); + setAttribute( p, 'svelte-3842350206', '' ); + var text = createText( text_value = state.foo ); + appendNode( text, p ); + + return { + mount: function ( target, anchor ) { + insertNode( p, target, anchor ); + }, + + update: function ( changed, state ) { + if ( text_value !== ( text_value = state.foo ) ) { + text.data = text_value; + } + }, + + destroy: function ( detach ) { + if ( detach ) { + detachNode( p ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = assign( template.data(), options.data ); + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + if ( !document.getElementById( "svelte-3842350206-style" ) ) add_css(); + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + this._fragment.update( newState, this._state ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/computed-collapsed-if/_actual-bundle.js b/test/js/samples/computed-collapsed-if/_actual-bundle.js new file mode 100644 index 000000000000..3f55eecc8028 --- /dev/null +++ b/test/js/samples/computed-collapsed-if/_actual-bundle.js @@ -0,0 +1,218 @@ +function noop () {} + +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +function recompute ( state, newState, oldState, isInitial ) { + if ( isInitial || ( 'x' in newState && differs( state.x, oldState.x ) ) ) { + state.a = newState.a = template.computed.a( state.x ); + state.b = newState.b = template.computed.b( state.x ); + } +} + +var template = (function () { + return { + computed: { + a: x => x * 2, + b: x => x * 3 + } + }; +}()); + +function create_main_fragment ( state, component ) { + + + return { + mount: noop, + + destroy: noop + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + recompute( this._state, this._state, {}, true ); + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + recompute( this._state, newState, oldState, false ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/computed-collapsed-if/expected-bundle.js b/test/js/samples/computed-collapsed-if/expected-bundle.js new file mode 100644 index 000000000000..3f55eecc8028 --- /dev/null +++ b/test/js/samples/computed-collapsed-if/expected-bundle.js @@ -0,0 +1,218 @@ +function noop () {} + +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +function recompute ( state, newState, oldState, isInitial ) { + if ( isInitial || ( 'x' in newState && differs( state.x, oldState.x ) ) ) { + state.a = newState.a = template.computed.a( state.x ); + state.b = newState.b = template.computed.b( state.x ); + } +} + +var template = (function () { + return { + computed: { + a: x => x * 2, + b: x => x * 3 + } + }; +}()); + +function create_main_fragment ( state, component ) { + + + return { + mount: noop, + + destroy: noop + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + recompute( this._state, this._state, {}, true ); + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + recompute( this._state, newState, oldState, false ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/each-block-changed-check/_actual-bundle.js b/test/js/samples/each-block-changed-check/_actual-bundle.js new file mode 100644 index 000000000000..b8895d8820aa --- /dev/null +++ b/test/js/samples/each-block-changed-check/_actual-bundle.js @@ -0,0 +1,341 @@ +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function appendNode ( node, target ) { + target.appendChild( node ); +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function detachBetween ( before, after ) { + while ( before.nextSibling && before.nextSibling !== after ) { + before.parentNode.removeChild( before.nextSibling ); + } +} + +function destroyEach ( iterations, detach, start ) { + for ( var i = start; i < iterations.length; i += 1 ) { + if ( iterations[i] ) iterations[i].destroy( detach ); + } +} + +function createElement ( name ) { + return document.createElement( name ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +function create_main_fragment ( state, component ) { + var text_1_value; + + var each_block_value = state.comments; + + var each_block_iterations = []; + + for ( var i = 0; i < each_block_value.length; i += 1 ) { + each_block_iterations[i] = create_each_block( state, each_block_value, each_block_value[i], i, component ); + } + + var text = createText( "\n\n" ); + var p = createElement( 'p' ); + var text_1 = createText( text_1_value = state.foo ); + appendNode( text_1, p ); + + return { + mount: function ( target, anchor ) { + for ( var i = 0; i < each_block_iterations.length; i += 1 ) { + each_block_iterations[i].mount( target, null ); + } + + insertNode( text, target, anchor ); + insertNode( p, target, anchor ); + }, + + update: function ( changed, state ) { + var each_block_value = state.comments; + + if ( 'comments' in changed || 'elapsed' in changed || 'time' in changed ) { + for ( var i = 0; i < each_block_value.length; i += 1 ) { + if ( each_block_iterations[i] ) { + each_block_iterations[i].update( changed, state, each_block_value, each_block_value[i], i ); + } else { + each_block_iterations[i] = create_each_block( state, each_block_value, each_block_value[i], i, component ); + each_block_iterations[i].mount( text.parentNode, text ); + } + } + + destroyEach( each_block_iterations, true, each_block_value.length ); + each_block_iterations.length = each_block_value.length; + } + + if ( text_1_value !== ( text_1_value = state.foo ) ) { + text_1.data = text_1_value; + } + }, + + destroy: function ( detach ) { + destroyEach( each_block_iterations, detach, 0 ); + + if ( detach ) { + detachNode( text ); + detachNode( p ); + } + } + }; +} + +function create_each_block ( state, each_block_value, comment, i, component ) { + var text_value, text_2_value, text_4_value; + + var div = createElement( 'div' ); + div.className = "comment"; + var strong = createElement( 'strong' ); + appendNode( strong, div ); + var text = createText( text_value = i ); + appendNode( text, strong ); + appendNode( createText( "\n\n\t\t" ), div ); + var span = createElement( 'span' ); + appendNode( span, div ); + span.className = "meta"; + var text_2 = createText( text_2_value = comment.author ); + appendNode( text_2, span ); + appendNode( createText( " wrote " ), span ); + var text_4 = createText( text_4_value = state.elapsed(comment.time, state.time) ); + appendNode( text_4, span ); + appendNode( createText( " ago:" ), span ); + appendNode( createText( "\n\n\t\t" ), div ); + var raw_before = createElement( 'noscript' ); + appendNode( raw_before, div ); + var raw_after = createElement( 'noscript' ); + appendNode( raw_after, div ); + var raw_value = comment.html; + raw_before.insertAdjacentHTML( 'afterend', raw_value ); + + return { + mount: function ( target, anchor ) { + insertNode( div, target, anchor ); + }, + + update: function ( changed, state, each_block_value, comment, i ) { + if ( text_value !== ( text_value = i ) ) { + text.data = text_value; + } + + if ( text_2_value !== ( text_2_value = comment.author ) ) { + text_2.data = text_2_value; + } + + if ( text_4_value !== ( text_4_value = state.elapsed(comment.time, state.time) ) ) { + text_4.data = text_4_value; + } + + if ( raw_value !== ( raw_value = comment.html ) ) { + detachBetween( raw_before, raw_after ); + raw_before.insertAdjacentHTML( 'afterend', raw_value ); + } + }, + + destroy: function ( detach ) { + if ( detach ) { + detachBetween( raw_before, raw_after ); + + detachNode( div ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + this._fragment.update( newState, this._state ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/each-block-changed-check/expected-bundle.js b/test/js/samples/each-block-changed-check/expected-bundle.js new file mode 100644 index 000000000000..b8895d8820aa --- /dev/null +++ b/test/js/samples/each-block-changed-check/expected-bundle.js @@ -0,0 +1,341 @@ +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function appendNode ( node, target ) { + target.appendChild( node ); +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function detachBetween ( before, after ) { + while ( before.nextSibling && before.nextSibling !== after ) { + before.parentNode.removeChild( before.nextSibling ); + } +} + +function destroyEach ( iterations, detach, start ) { + for ( var i = start; i < iterations.length; i += 1 ) { + if ( iterations[i] ) iterations[i].destroy( detach ); + } +} + +function createElement ( name ) { + return document.createElement( name ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +function create_main_fragment ( state, component ) { + var text_1_value; + + var each_block_value = state.comments; + + var each_block_iterations = []; + + for ( var i = 0; i < each_block_value.length; i += 1 ) { + each_block_iterations[i] = create_each_block( state, each_block_value, each_block_value[i], i, component ); + } + + var text = createText( "\n\n" ); + var p = createElement( 'p' ); + var text_1 = createText( text_1_value = state.foo ); + appendNode( text_1, p ); + + return { + mount: function ( target, anchor ) { + for ( var i = 0; i < each_block_iterations.length; i += 1 ) { + each_block_iterations[i].mount( target, null ); + } + + insertNode( text, target, anchor ); + insertNode( p, target, anchor ); + }, + + update: function ( changed, state ) { + var each_block_value = state.comments; + + if ( 'comments' in changed || 'elapsed' in changed || 'time' in changed ) { + for ( var i = 0; i < each_block_value.length; i += 1 ) { + if ( each_block_iterations[i] ) { + each_block_iterations[i].update( changed, state, each_block_value, each_block_value[i], i ); + } else { + each_block_iterations[i] = create_each_block( state, each_block_value, each_block_value[i], i, component ); + each_block_iterations[i].mount( text.parentNode, text ); + } + } + + destroyEach( each_block_iterations, true, each_block_value.length ); + each_block_iterations.length = each_block_value.length; + } + + if ( text_1_value !== ( text_1_value = state.foo ) ) { + text_1.data = text_1_value; + } + }, + + destroy: function ( detach ) { + destroyEach( each_block_iterations, detach, 0 ); + + if ( detach ) { + detachNode( text ); + detachNode( p ); + } + } + }; +} + +function create_each_block ( state, each_block_value, comment, i, component ) { + var text_value, text_2_value, text_4_value; + + var div = createElement( 'div' ); + div.className = "comment"; + var strong = createElement( 'strong' ); + appendNode( strong, div ); + var text = createText( text_value = i ); + appendNode( text, strong ); + appendNode( createText( "\n\n\t\t" ), div ); + var span = createElement( 'span' ); + appendNode( span, div ); + span.className = "meta"; + var text_2 = createText( text_2_value = comment.author ); + appendNode( text_2, span ); + appendNode( createText( " wrote " ), span ); + var text_4 = createText( text_4_value = state.elapsed(comment.time, state.time) ); + appendNode( text_4, span ); + appendNode( createText( " ago:" ), span ); + appendNode( createText( "\n\n\t\t" ), div ); + var raw_before = createElement( 'noscript' ); + appendNode( raw_before, div ); + var raw_after = createElement( 'noscript' ); + appendNode( raw_after, div ); + var raw_value = comment.html; + raw_before.insertAdjacentHTML( 'afterend', raw_value ); + + return { + mount: function ( target, anchor ) { + insertNode( div, target, anchor ); + }, + + update: function ( changed, state, each_block_value, comment, i ) { + if ( text_value !== ( text_value = i ) ) { + text.data = text_value; + } + + if ( text_2_value !== ( text_2_value = comment.author ) ) { + text_2.data = text_2_value; + } + + if ( text_4_value !== ( text_4_value = state.elapsed(comment.time, state.time) ) ) { + text_4.data = text_4_value; + } + + if ( raw_value !== ( raw_value = comment.html ) ) { + detachBetween( raw_before, raw_after ); + raw_before.insertAdjacentHTML( 'afterend', raw_value ); + } + }, + + destroy: function ( detach ) { + if ( detach ) { + detachBetween( raw_before, raw_after ); + + detachNode( div ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + this._fragment.update( newState, this._state ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/event-handlers-custom/_actual-bundle.js b/test/js/samples/event-handlers-custom/_actual-bundle.js new file mode 100644 index 000000000000..da8e5905e617 --- /dev/null +++ b/test/js/samples/event-handlers-custom/_actual-bundle.js @@ -0,0 +1,248 @@ +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function appendNode ( node, target ) { + target.appendChild( node ); +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function createElement ( name ) { + return document.createElement( name ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +var template = (function () { + return { + methods: { + foo ( bar ) { + console.log( bar ); + } + }, + events: { + foo ( node, callback ) { + // code goes here + } + } + }; +}()); + +function create_main_fragment ( state, component ) { + var button = createElement( 'button' ); + + var foo_handler = template.events.foo.call( component, button, function ( event ) { + var state = component.get(); + component.foo( state.bar ); + }); + + appendNode( createText( "foo" ), button ); + + return { + mount: function ( target, anchor ) { + insertNode( button, target, anchor ); + }, + + destroy: function ( detach ) { + foo_handler.teardown(); + + if ( detach ) { + detachNode( button ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, template.methods, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/event-handlers-custom/expected-bundle.js b/test/js/samples/event-handlers-custom/expected-bundle.js new file mode 100644 index 000000000000..da8e5905e617 --- /dev/null +++ b/test/js/samples/event-handlers-custom/expected-bundle.js @@ -0,0 +1,248 @@ +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function appendNode ( node, target ) { + target.appendChild( node ); +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function createElement ( name ) { + return document.createElement( name ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +var template = (function () { + return { + methods: { + foo ( bar ) { + console.log( bar ); + } + }, + events: { + foo ( node, callback ) { + // code goes here + } + } + }; +}()); + +function create_main_fragment ( state, component ) { + var button = createElement( 'button' ); + + var foo_handler = template.events.foo.call( component, button, function ( event ) { + var state = component.get(); + component.foo( state.bar ); + }); + + appendNode( createText( "foo" ), button ); + + return { + mount: function ( target, anchor ) { + insertNode( button, target, anchor ); + }, + + destroy: function ( detach ) { + foo_handler.teardown(); + + if ( detach ) { + detachNode( button ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, template.methods, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/if-block-no-update/_actual-bundle.js b/test/js/samples/if-block-no-update/_actual-bundle.js new file mode 100644 index 000000000000..b48b9e1fe70f --- /dev/null +++ b/test/js/samples/if-block-no-update/_actual-bundle.js @@ -0,0 +1,282 @@ +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function appendNode ( node, target ) { + target.appendChild( node ); +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function createElement ( name ) { + return document.createElement( name ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +function createComment () { + return document.createComment( '' ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +function create_main_fragment ( state, component ) { + function get_block ( state ) { + if ( state.foo ) return create_if_block; + return create_if_block_1; + } + + var current_block = get_block( state ); + var if_block = current_block( state, component ); + + var if_block_anchor = createComment(); + + return { + mount: function ( target, anchor ) { + if_block.mount( target, anchor ); + insertNode( if_block_anchor, target, anchor ); + }, + + update: function ( changed, state ) { + if ( current_block !== ( current_block = get_block( state ) ) ) { + if_block.destroy( true ); + if_block = current_block( state, component ); + if_block.mount( if_block_anchor.parentNode, if_block_anchor ); + } + }, + + destroy: function ( detach ) { + if_block.destroy( detach ); + + if ( detach ) { + detachNode( if_block_anchor ); + } + } + }; +} + +function create_if_block ( state, component ) { + var p = createElement( 'p' ); + appendNode( createText( "foo!" ), p ); + + return { + mount: function ( target, anchor ) { + insertNode( p, target, anchor ); + }, + + destroy: function ( detach ) { + if ( detach ) { + detachNode( p ); + } + } + }; +} + +function create_if_block_1 ( state, component ) { + var p = createElement( 'p' ); + appendNode( createText( "not foo!" ), p ); + + return { + mount: function ( target, anchor ) { + insertNode( p, target, anchor ); + }, + + destroy: function ( detach ) { + if ( detach ) { + detachNode( p ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + this._fragment.update( newState, this._state ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/if-block-no-update/expected-bundle.js b/test/js/samples/if-block-no-update/expected-bundle.js new file mode 100644 index 000000000000..b48b9e1fe70f --- /dev/null +++ b/test/js/samples/if-block-no-update/expected-bundle.js @@ -0,0 +1,282 @@ +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function appendNode ( node, target ) { + target.appendChild( node ); +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function createElement ( name ) { + return document.createElement( name ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +function createComment () { + return document.createComment( '' ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +function create_main_fragment ( state, component ) { + function get_block ( state ) { + if ( state.foo ) return create_if_block; + return create_if_block_1; + } + + var current_block = get_block( state ); + var if_block = current_block( state, component ); + + var if_block_anchor = createComment(); + + return { + mount: function ( target, anchor ) { + if_block.mount( target, anchor ); + insertNode( if_block_anchor, target, anchor ); + }, + + update: function ( changed, state ) { + if ( current_block !== ( current_block = get_block( state ) ) ) { + if_block.destroy( true ); + if_block = current_block( state, component ); + if_block.mount( if_block_anchor.parentNode, if_block_anchor ); + } + }, + + destroy: function ( detach ) { + if_block.destroy( detach ); + + if ( detach ) { + detachNode( if_block_anchor ); + } + } + }; +} + +function create_if_block ( state, component ) { + var p = createElement( 'p' ); + appendNode( createText( "foo!" ), p ); + + return { + mount: function ( target, anchor ) { + insertNode( p, target, anchor ); + }, + + destroy: function ( detach ) { + if ( detach ) { + detachNode( p ); + } + } + }; +} + +function create_if_block_1 ( state, component ) { + var p = createElement( 'p' ); + appendNode( createText( "not foo!" ), p ); + + return { + mount: function ( target, anchor ) { + insertNode( p, target, anchor ); + }, + + destroy: function ( detach ) { + if ( detach ) { + detachNode( p ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + this._fragment.update( newState, this._state ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/if-block-simple/_actual-bundle.js b/test/js/samples/if-block-simple/_actual-bundle.js new file mode 100644 index 000000000000..4463844f44f0 --- /dev/null +++ b/test/js/samples/if-block-simple/_actual-bundle.js @@ -0,0 +1,263 @@ +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function appendNode ( node, target ) { + target.appendChild( node ); +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function createElement ( name ) { + return document.createElement( name ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +function createComment () { + return document.createComment( '' ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +function create_main_fragment ( state, component ) { + var if_block = (state.foo) && create_if_block( state, component ); + + var if_block_anchor = createComment(); + + return { + mount: function ( target, anchor ) { + if ( if_block ) if_block.mount( target, anchor ); + insertNode( if_block_anchor, target, anchor ); + }, + + update: function ( changed, state ) { + if ( state.foo ) { + if ( !if_block ) { + if_block = create_if_block( state, component ); + if_block.mount( if_block_anchor.parentNode, if_block_anchor ); + } + } else if ( if_block ) { + if_block.destroy( true ); + if_block = null; + } + }, + + destroy: function ( detach ) { + if ( if_block ) if_block.destroy( detach ); + + if ( detach ) { + detachNode( if_block_anchor ); + } + } + }; +} + +function create_if_block ( state, component ) { + var p = createElement( 'p' ); + appendNode( createText( "foo!" ), p ); + + return { + mount: function ( target, anchor ) { + insertNode( p, target, anchor ); + }, + + destroy: function ( detach ) { + if ( detach ) { + detachNode( p ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + this._fragment.update( newState, this._state ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/if-block-simple/expected-bundle.js b/test/js/samples/if-block-simple/expected-bundle.js new file mode 100644 index 000000000000..4463844f44f0 --- /dev/null +++ b/test/js/samples/if-block-simple/expected-bundle.js @@ -0,0 +1,263 @@ +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function appendNode ( node, target ) { + target.appendChild( node ); +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function createElement ( name ) { + return document.createElement( name ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +function createComment () { + return document.createComment( '' ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +function create_main_fragment ( state, component ) { + var if_block = (state.foo) && create_if_block( state, component ); + + var if_block_anchor = createComment(); + + return { + mount: function ( target, anchor ) { + if ( if_block ) if_block.mount( target, anchor ); + insertNode( if_block_anchor, target, anchor ); + }, + + update: function ( changed, state ) { + if ( state.foo ) { + if ( !if_block ) { + if_block = create_if_block( state, component ); + if_block.mount( if_block_anchor.parentNode, if_block_anchor ); + } + } else if ( if_block ) { + if_block.destroy( true ); + if_block = null; + } + }, + + destroy: function ( detach ) { + if ( if_block ) if_block.destroy( detach ); + + if ( detach ) { + detachNode( if_block_anchor ); + } + } + }; +} + +function create_if_block ( state, component ) { + var p = createElement( 'p' ); + appendNode( createText( "foo!" ), p ); + + return { + mount: function ( target, anchor ) { + insertNode( p, target, anchor ); + }, + + destroy: function ( detach ) { + if ( detach ) { + detachNode( p ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + this._fragment.update( newState, this._state ); + dispatchObservers( this, this._observers.post, newState, oldState ); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/non-imported-component/_actual-bundle.js b/test/js/samples/non-imported-component/_actual-bundle.js new file mode 100644 index 000000000000..5f2e7320a335 --- /dev/null +++ b/test/js/samples/non-imported-component/_actual-bundle.js @@ -0,0 +1,244 @@ +import Imported from 'Imported.html'; + +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +var template = (function () { + return { + components: { + NonImported + } + }; +}()); + +function create_main_fragment ( state, component ) { + var imported = new Imported({ + target: null, + _root: component._root + }); + + var text = createText( "\n" ); + + var nonimported = new template.components.NonImported({ + target: null, + _root: component._root + }); + + return { + mount: function ( target, anchor ) { + imported._fragment.mount( target, anchor ); + insertNode( text, target, anchor ); + nonimported._fragment.mount( target, anchor ); + }, + + destroy: function ( detach ) { + imported.destroy( detach ); + nonimported.destroy( detach ); + + if ( detach ) { + detachNode( text ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + this._renderHooks = []; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); + this._flush(); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + dispatchObservers( this, this._observers.post, newState, oldState ); + this._flush(); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/non-imported-component/expected-bundle.js b/test/js/samples/non-imported-component/expected-bundle.js new file mode 100644 index 000000000000..5f2e7320a335 --- /dev/null +++ b/test/js/samples/non-imported-component/expected-bundle.js @@ -0,0 +1,244 @@ +import Imported from 'Imported.html'; + +function assign ( target ) { + for ( var i = 1; i < arguments.length; i += 1 ) { + var source = arguments[i]; + for ( var k in source ) target[k] = source[k]; + } + + return target; +} + +function insertNode ( node, target, anchor ) { + target.insertBefore( node, anchor ); +} + +function detachNode ( node ) { + node.parentNode.removeChild( node ); +} + +function createText ( data ) { + return document.createTextNode( data ); +} + +var transitionManager = { + running: false, + transitions: [], + + add: function ( transition ) { + transitionManager.transitions.push( transition ); + + if ( !this.running ) { + this.running = true; + this.next(); + } + }, + + next: function () { + transitionManager.running = false; + + var now = window.performance.now(); + var i = transitionManager.transitions.length; + + while ( i-- ) { + var transition = transitionManager.transitions[i]; + + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + + if ( transition.running ) { + transition.update( now ); + transitionManager.running = true; + } else if ( !transition.pending ) { + transitionManager.transitions.splice( i, 1 ); + } + } + + if ( transitionManager.running ) { + requestAnimationFrame( transitionManager.next ); + } + } +}; + +function differs ( a, b ) { + return ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) ); +} + +function dispatchObservers ( component, group, newState, oldState ) { + for ( var key in group ) { + if ( !( key in newState ) ) continue; + + var newValue = newState[ key ]; + var oldValue = oldState[ key ]; + + 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; + } + } + } +} + +function get ( key ) { + return key ? this._state[ key ] : this._state; +} + +function fire ( eventName, data ) { + var handlers = eventName in this._handlers && this._handlers[ eventName ].slice(); + if ( !handlers ) return; + + for ( var i = 0; i < handlers.length; i += 1 ) { + handlers[i].call( this, data ); + } +} + +function observe ( key, callback, options ) { + var group = ( options && options.defer ) ? this._observers.post : this._observers.pre; + + ( 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 ); + } + }; +} + +function on ( eventName, handler ) { + if ( eventName === 'teardown' ) 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 ); + } + }; +} + +function set ( newState ) { + this._set( assign( {}, newState ) ); + this._root._flush(); +} + +function _flush () { + if ( !this._renderHooks ) return; + + while ( this._renderHooks.length ) { + this._renderHooks.pop()(); + } +} + +var proto = { + get: get, + fire: fire, + observe: observe, + on: on, + set: set, + _flush: _flush +}; + +var template = (function () { + return { + components: { + NonImported + } + }; +}()); + +function create_main_fragment ( state, component ) { + var imported = new Imported({ + target: null, + _root: component._root + }); + + var text = createText( "\n" ); + + var nonimported = new template.components.NonImported({ + target: null, + _root: component._root + }); + + return { + mount: function ( target, anchor ) { + imported._fragment.mount( target, anchor ); + insertNode( text, target, anchor ); + nonimported._fragment.mount( target, anchor ); + }, + + destroy: function ( detach ) { + imported.destroy( detach ); + nonimported.destroy( detach ); + + if ( detach ) { + detachNode( text ); + } + } + }; +} + +function SvelteComponent ( options ) { + options = options || {}; + this._state = options.data || {}; + + this._observers = { + pre: Object.create( null ), + post: Object.create( null ) + }; + + this._handlers = Object.create( null ); + + this._root = options._root || this; + this._yield = options._yield; + + this._torndown = false; + this._renderHooks = []; + + this._fragment = create_main_fragment( this._state, this ); + if ( options.target ) this._fragment.mount( options.target, null ); + this._flush(); +} + +assign( SvelteComponent.prototype, proto ); + +SvelteComponent.prototype._set = function _set ( newState ) { + var oldState = this._state; + this._state = assign( {}, oldState, newState ); + dispatchObservers( this, this._observers.pre, newState, oldState ); + dispatchObservers( this, this._observers.post, newState, oldState ); + this._flush(); +}; + +SvelteComponent.prototype.teardown = SvelteComponent.prototype.destroy = function destroy ( detach ) { + this.fire( 'destroy' ); + + this._fragment.destroy( detach !== false ); + this._fragment = null; + + this._state = {}; + this._torndown = true; +}; + +export default SvelteComponent; diff --git a/test/js/samples/non-imported-component/expected.js b/test/js/samples/non-imported-component/expected.js index 12e28c91191f..602b33086ead 100644 --- a/test/js/samples/non-imported-component/expected.js +++ b/test/js/samples/non-imported-component/expected.js @@ -1,4 +1,4 @@ -import Imported from './Imported.html'; +import Imported from 'Imported.html'; import { assign, createText, detachNode, dispatchObservers, insertNode, proto } from "svelte/shared.js"; diff --git a/test/js/samples/non-imported-component/input.html b/test/js/samples/non-imported-component/input.html index 74a8abc24405..f65561020e8b 100644 --- a/test/js/samples/non-imported-component/input.html +++ b/test/js/samples/non-imported-component/input.html @@ -2,7 +2,7 @@