add development warnings for missing data properties with dev: true (#13)

pull/320/head
Rich Harris 8 years ago
parent 62c8ef42ff
commit d61b1927b2

@ -19,6 +19,10 @@ export default class Generator {
this.components = {}; this.components = {};
this.events = {}; this.events = {};
// track which properties are needed, so we can provide useful info
// in dev mode
this.expectedProperties = {};
this.elementDepth = 0; this.elementDepth = 0;
this.code = new MagicString( source ); this.code = new MagicString( source );
@ -99,6 +103,10 @@ export default class Generator {
} }
}); });
dependencies.forEach( name => {
this.expectedProperties[ name ] = true;
});
return { return {
dependencies, dependencies,
contexts: usedContexts, contexts: usedContexts,

@ -291,13 +291,32 @@ export default function dom ( parsed, source, options, names ) {
` ); ` );
} }
const initialState = templateProperties.data ? `Object.assign( template.data(), options.data )` : `options.data || {}`; const stateBlock = new CodeBuilder();
stateBlock.addLine(
`this._state = ${templateProperties.data ? `Object.assign( template.data(), options.data )` : `options.data || {}`};`
);
if ( templateProperties.computed ) {
stateBlock.addLine(
`applyComputations( this._state, this._state, {}, true );`
);
}
if ( options.dev ) {
Object.keys( generator.expectedProperties ).forEach( prop => {
stateBlock.addLine(
`if ( !( '${prop}' in this._state ) ) throw new Error( "Component was created without expected data property 'foo'" );`
);
});
}
builders.main.addBlock( deindent` builders.main.addBlock( deindent`
function ${name} ( options ) { function ${name} ( options ) {
options = options || {}; options = options || {};
${generator.usesRefs ? `\nthis.refs = {}` : ``} ${generator.usesRefs ? `\nthis.refs = {}` : ``}
this._state = ${initialState};${templateProperties.computed ? `\napplyComputations( this._state, this._state, {}, true );` : ``}
${stateBlock}
this._observers = { this._observers = {
pre: Object.create( null ), pre: Object.create( null ),

@ -41,6 +41,7 @@ describe( 'generate', () => {
showCompiledCode = config.show; showCompiledCode = config.show;
compileOptions = config.compileOptions || {}; compileOptions = config.compileOptions || {};
compileOptions.shared = shared; compileOptions.shared = shared;
compileOptions.dev = config.dev;
try { try {
const source = fs.readFileSync( `test/generator/${dir}/main.html`, 'utf-8' ); const source = fs.readFileSync( `test/generator/${dir}/main.html`, 'utf-8' );
@ -79,6 +80,8 @@ describe( 'generate', () => {
throw err; throw err;
} }
let unintendedError = null;
return env() return env()
.then( window => { .then( window => {
// Put the constructor on window for testing // Put the constructor on window for testing
@ -91,6 +94,11 @@ describe( 'generate', () => {
data: config.data data: config.data
}); });
if ( config.error ) {
unintendedError = true;
throw new Error( 'Expected a runtime error' );
}
if ( config.html ) { if ( config.html ) {
assert.htmlEqual( target.innerHTML, config.html ); assert.htmlEqual( target.innerHTML, config.html );
} }
@ -103,8 +111,14 @@ describe( 'generate', () => {
} }
}) })
.catch( err => { .catch( err => {
if ( !config.show ) console.log( addLineNumbers( code ) ); // eslint-disable-line no-console if ( config.error && !unintendedError ) {
throw err; config.error( assert, err );
}
else {
if ( !config.show ) console.log( addLineNumbers( code ) ); // eslint-disable-line no-console
throw err;
}
}); });
}); });
} }

@ -0,0 +1,7 @@
export default {
dev: true,
error ( assert, err ) {
assert.equal( err.message, `Component was created without expected data property 'foo'` );
}
};
Loading…
Cancel
Save