diff --git a/src/generators/Generator.js b/src/generators/Generator.js
index e25fdc5a9bea..f3aa58dc26be 100644
--- a/src/generators/Generator.js
+++ b/src/generators/Generator.js
@@ -9,12 +9,13 @@ import getOutro from './shared/utils/getOutro.js';
import annotateWithScopes from './annotateWithScopes.js';
export default class Generator {
- constructor ( parsed, source, name, names, visitors ) {
+ constructor ( parsed, source, name, names, visitors, options ) {
this.parsed = parsed;
this.source = source;
this.name = name;
this.names = names;
this.visitors = visitors;
+ this.options = options;
this.imports = [];
this.helpers = {};
diff --git a/src/generators/dom/index.js b/src/generators/dom/index.js
index 26795ebff54a..3c337a2f2a4a 100644
--- a/src/generators/dom/index.js
+++ b/src/generators/dom/index.js
@@ -8,8 +8,8 @@ import Generator from '../Generator.js';
import * as shared from '../../shared/index.js';
class DomGenerator extends Generator {
- constructor ( parsed, source, name, names, visitors ) {
- super( parsed, source, name, names, visitors );
+ constructor ( parsed, source, name, names, visitors, options ) {
+ super( parsed, source, name, names, visitors, options );
this.renderers = [];
this.uses = {};
@@ -132,6 +132,10 @@ class DomGenerator extends Generator {
}
helper ( name ) {
+ if ( this.options.dev && `${name}Dev` in shared ) {
+ name = `${name}Dev`;
+ }
+
this.uses[ name ] = true;
if ( !( name in this.aliases ) ) {
@@ -152,7 +156,7 @@ export default function dom ( parsed, source, options, names ) {
const format = options.format || 'es';
const name = options.name || 'SvelteComponent';
- const generator = new DomGenerator( parsed, source, name, names, visitors );
+ const generator = new DomGenerator( parsed, source, name, names, visitors, options );
const { computations, templateProperties } = generator.parseJs();
@@ -359,34 +363,20 @@ export default function dom ( parsed, source, options, names ) {
}
` );
- if ( templateProperties.methods ) {
- builders.main.addBlock( `${name}.prototype = template.methods;` );
- }
-
const sharedPath = options.shared === true ? 'svelte/shared.js' : options.shared;
- builders.main.addBlock( sharedPath ?
- deindent`
- ${name}.prototype.get = ${generator.helper( 'get' )};
- ${name}.prototype.fire = ${generator.helper( 'fire' )};
- ${name}.prototype.observe = ${generator.helper( 'observe' )};
- ${name}.prototype.on = ${generator.helper( 'on' )};
- ${name}.prototype.set = ${generator.helper( 'set' )};
- ${name}.prototype._flush = ${generator.helper( '_flush' )};
- ` :
- deindent`
- ${name}.prototype.get = ${shared.get};
-
- ${name}.prototype.fire = ${shared.fire};
-
- ${name}.prototype.observe = ${shared.observe};
-
- ${name}.prototype.on = ${shared.on};
-
- ${name}.prototype.set = ${shared.set};
+ if ( sharedPath ) {
+ const base = templateProperties.methods ? `{}, template.methods` : `{}`;
+ builders.main.addBlock( `${name}.prototype = Object.assign( ${base}, ${generator.helper( 'proto' )} );` );
+ } else {
+ if ( templateProperties.methods ) {
+ builders.main.addBlock( `${name}.prototype = template.methods;` );
+ }
- ${name}.prototype._flush = ${shared._flush};
- ` );
+ [ 'get', 'fire', 'observe', 'on', 'set', '_flush' ].forEach( methodName => {
+ builders.main.addLine( `${name}.prototype.${methodName} = ${generator.helper( methodName )};` );
+ });
+ }
// TODO deprecate component.teardown()
builders.main.addBlock( deindent`
@@ -395,7 +385,7 @@ export default function dom ( parsed, source, options, names ) {
};
${name}.prototype.teardown = ${name}.prototype.destroy = function destroy ( detach ) {
- this.fire( 'teardown' );${templateProperties.ondestroy ? `\ntemplate.ondestroy.call( this );` : ``}
+ this.fire( 'destroy' );${templateProperties.ondestroy ? `\ntemplate.ondestroy.call( this );` : ``}
this._fragment.teardown( detach !== false );
this._fragment = null;
@@ -420,13 +410,9 @@ export default function dom ( parsed, source, options, names ) {
} else {
Object.keys( generator.uses ).forEach( key => {
const fn = shared[ key ]; // eslint-disable-line import/namespace
- if ( key !== generator.aliases[ key ] ) {
- builders.main.addBlock( `var ${generator.aliases[ key ]} = ${fn.toString()}}` );
- } else {
- builders.main.addBlock( fn.toString() );
- }
+ builders.main.addBlock( fn.toString().replace( /^function [^(]*/, 'function ' + generator.aliases[ key ] ) );
});
}
return generator.generate( builders.main.toString(), options, { name, format } );
-}
+}
\ No newline at end of file
diff --git a/src/generators/server-side-rendering/index.js b/src/generators/server-side-rendering/index.js
index 0ff75221fd93..285fb3cca6dc 100644
--- a/src/generators/server-side-rendering/index.js
+++ b/src/generators/server-side-rendering/index.js
@@ -5,8 +5,8 @@ import visitors from './visitors/index.js';
import Generator from '../Generator.js';
class SsrGenerator extends Generator {
- constructor ( parsed, source, name, names, visitors ) {
- super( parsed, source, name, names, visitors );
+ constructor ( parsed, source, name, names, visitors, options ) {
+ super( parsed, source, name, names, visitors, options );
this.bindings = [];
this.renderCode = '';
}
@@ -36,7 +36,7 @@ export default function ssr ( parsed, source, options, names ) {
const format = options.format || 'cjs';
const name = options.name || 'SvelteComponent';
- const generator = new SsrGenerator( parsed, source, name, names, visitors );
+ const generator = new SsrGenerator( parsed, source, name, names, visitors, options );
const { computations, templateProperties } = generator.parseJs();
diff --git a/src/shared/methods.js b/src/shared/methods.js
index 34bcdac49817..395420767dde 100644
--- a/src/shared/methods.js
+++ b/src/shared/methods.js
@@ -30,7 +30,53 @@ export function observe ( key, callback, options ) {
};
}
+export function observeDev ( key, callback, options ) {
+ var c = ( key = '' + key ).search( /[^\w]/ );
+ if ( c > -1 ) {
+ var message = "The first argument to component.observe(...) must be the name of a top-level property";
+ if ( c > 0 ) message += ", i.e. '" + key.slice( 0, c ) + "' rather than '" + key + "'";
+
+ throw new Error( message );
+ }
+
+ var group = ( options && options.defer ) ? this._observers.pre : this._observers.post;
+
+ ( group[ key ] || ( group[ key ] = [] ) ).push( callback );
+
+ if ( !options || options.init !== false ) {
+ callback.__calling = true;
+ callback.call( this, this._state[ key ] );
+ callback.__calling = false;
+ }
+
+ return {
+ cancel: function () {
+ var index = group[ key ].indexOf( callback );
+ if ( ~index ) group[ key ].splice( index, 1 );
+ }
+ };
+}
+
export 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 );
+ }
+ };
+}
+
+export function onDev ( eventName, handler ) {
+ if ( eventName === 'teardown' ) {
+ console.warn( "Use component.on('destroy', ...) instead of component.on('teardown', ...) which has been deprecated and will be unsupported in Svelte 2" );
+ return this.on( 'destroy', handler );
+ }
+
var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
handlers.push( handler );
@@ -55,3 +101,21 @@ export function _flush () {
hook.fn.call( hook.context );
}
}
+
+export var proto = {
+ get: get,
+ fire: fire,
+ observe: observe,
+ on: on,
+ set: set,
+ _flush: _flush
+};
+
+export var protoDev = {
+ get: get,
+ fire: fire,
+ observe: observeDev,
+ on: onDev,
+ set: set,
+ _flush: _flush
+};
\ No newline at end of file
diff --git a/test/generator/index.js b/test/generator/index.js
index 2f647bec1a72..f52831b7c21e 100644
--- a/test/generator/index.js
+++ b/test/generator/index.js
@@ -98,16 +98,31 @@ describe( 'generate', () => {
const target = window.document.querySelector( 'main' );
+ const warnings = [];
+ const warn = console.warn;
+ console.warn = warning => {
+ warnings.push( warning );
+ };
+
const component = new SvelteComponent({
target,
data: config.data
});
+ console.warn = warn;
+
if ( config.error ) {
unintendedError = true;
throw new Error( 'Expected a runtime error' );
}
+ if ( config.warnings ) {
+ assert.deepEqual( warnings, config.warnings );
+ } else if ( warnings.length ) {
+ unintendedError = true;
+ throw new Error( 'Received unexpected warnings' );
+ }
+
if ( config.html ) {
assert.htmlEqual( target.innerHTML, config.html );
}
diff --git a/test/generator/samples/dev-warning-bad-observe-arguments/_config.js b/test/generator/samples/dev-warning-bad-observe-arguments/_config.js
new file mode 100644
index 000000000000..0b9183aeba49
--- /dev/null
+++ b/test/generator/samples/dev-warning-bad-observe-arguments/_config.js
@@ -0,0 +1,7 @@
+export default {
+ dev: true,
+
+ error ( assert, err ) {
+ assert.equal( err.message, `The first argument to component.observe(...) must be the name of a top-level property, i.e. 'nested' rather than 'nested.data'` );
+ }
+};
\ No newline at end of file
diff --git a/test/generator/samples/dev-warning-bad-observe-arguments/main.html b/test/generator/samples/dev-warning-bad-observe-arguments/main.html
new file mode 100644
index 000000000000..e15ae99fa4d7
--- /dev/null
+++ b/test/generator/samples/dev-warning-bad-observe-arguments/main.html
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/test/generator/samples/dev-warning-destroy-not-teardown/_config.js b/test/generator/samples/dev-warning-destroy-not-teardown/_config.js
new file mode 100644
index 000000000000..7e9b391f4ba5
--- /dev/null
+++ b/test/generator/samples/dev-warning-destroy-not-teardown/_config.js
@@ -0,0 +1,7 @@
+export default {
+ dev: true,
+
+ warnings: [
+ `Use component.on('destroy', ...) instead of component.on('teardown', ...) which has been deprecated and will be unsupported in Svelte 2`
+ ]
+};
\ No newline at end of file
diff --git a/test/generator/samples/dev-warning-destroy-not-teardown/main.html b/test/generator/samples/dev-warning-destroy-not-teardown/main.html
new file mode 100644
index 000000000000..22c2e9c28760
--- /dev/null
+++ b/test/generator/samples/dev-warning-destroy-not-teardown/main.html
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/test/generator/samples/events-lifecycle/_config.js b/test/generator/samples/events-lifecycle/_config.js
index 3303728f516b..ddd62238402d 100644
--- a/test/generator/samples/events-lifecycle/_config.js
+++ b/test/generator/samples/events-lifecycle/_config.js
@@ -2,7 +2,7 @@ export default {
test ( assert, component ) {
let count = 0;
- component.on( 'teardown', function () {
+ component.on( 'destroy', function () {
assert.equal( this, component );
count += 1;
});