diff --git a/src/compile/Component.ts b/src/compile/Component.ts index 84861806aa..e972ad5ee4 100644 --- a/src/compile/Component.ts +++ b/src/compile/Component.ts @@ -69,6 +69,7 @@ export default class Component { reactive_declaration_nodes: Set = new Set(); has_reactive_assignments = false; injected_reactive_declaration_vars: Set = new Set(); + helpers: Set = new Set(); indirectDependencies: Map> = new Map(); @@ -114,10 +115,6 @@ export default class Component { this.componentOptions = process_component_options(this, this.ast.html.children); this.namespace = namespaces[this.componentOptions.namespace] || this.componentOptions.namespace; - if (this.componentOptions.props) { - this.has_reactive_assignments = true; - } - if (compileOptions.customElement === true && !this.componentOptions.tag) { throw new Error(`No tag name specified`); // TODO better error } @@ -131,6 +128,13 @@ export default class Component { this.walk_module_js(); this.walk_instance_js_pre_template(); + if (this.componentOptions.props) { + this.has_reactive_assignments = true; + + const variable = this.var_lookup.get(this.componentOptions.props_object); + variable.reassigned = true; + } + this.name = this.getUniqueName(name); this.fragment = new Fragment(this, ast.html); @@ -196,14 +200,12 @@ export default class Component { const banner = `/* ${this.file ? `${this.file} ` : ``}generated by Svelte v${"__VERSION__"} */`; - const helpers = new Set(); - // TODO use same regex for both result = result.replace(compileOptions.generate === 'ssr' ? /(@+|#+)(\w*(?:-\w*)?)/g : /(@+)(\w*(?:-\w*)?)/g, (match: string, sigil: string, name: string) => { if (sigil === '@') { if (internal_exports.has(name)) { if (compileOptions.dev && internal_exports.has(`${name}Dev`)) name = `${name}Dev`; - helpers.add(name); + this.helpers.add(name); } return this.alias(name); @@ -212,7 +214,7 @@ export default class Component { return sigil.slice(1) + name; }); - const importedHelpers = Array.from(helpers) + const importedHelpers = Array.from(this.helpers) .sort() .map(name => { const alias = this.alias(name); @@ -761,9 +763,14 @@ export default class Component { }); } + // can't use the @ trick here, because we're + // manipulating the underlying magic string + component.helpers.add('exclude_internal_props'); + const exclude_internal_props = component.alias('exclude_internal_props'); + const suffix = code.original[declarator.end] === ';' - ? ` = $$props` - : ` = $$props;` + ? ` = ${exclude_internal_props}($$props)` + : ` = ${exclude_internal_props}($$props);` if (declarator.id.end === declarator.end) { code.appendLeft(declarator.end, suffix); diff --git a/src/internal/utils.js b/src/internal/utils.js index 5ac71b4fce..2e93efb44b 100644 --- a/src/internal/utils.js +++ b/src/internal/utils.js @@ -60,3 +60,8 @@ export function get_slot_context(definition, ctx, fn) { : ctx.$$scope.ctx; } +export function exclude_internal_props(props) { + const result = {}; + for (const k in props) if (k[0] !== '$') result[k] = props[k]; + return result; +} \ No newline at end of file diff --git a/test/runtime/samples/props-excludes-external/RenderProps.svelte b/test/runtime/samples/props-excludes-external/RenderProps.svelte new file mode 100644 index 0000000000..ef9cb989cf --- /dev/null +++ b/test/runtime/samples/props-excludes-external/RenderProps.svelte @@ -0,0 +1,7 @@ + + + + +

{JSON.stringify(props)}

\ No newline at end of file diff --git a/test/runtime/samples/props-excludes-external/_config.js b/test/runtime/samples/props-excludes-external/_config.js new file mode 100644 index 0000000000..fc3c71d6f0 --- /dev/null +++ b/test/runtime/samples/props-excludes-external/_config.js @@ -0,0 +1,17 @@ +export default { + props: { + x: 1 + }, + + html: ` +

{"x":1}

+ `, + + test({ assert, component, target }) { + component.x = 2; + + assert.htmlEqual(target.innerHTML, ` +

{"x":2}

+ `); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/props-excludes-external/main.svelte b/test/runtime/samples/props-excludes-external/main.svelte new file mode 100644 index 0000000000..4a04faf348 --- /dev/null +++ b/test/runtime/samples/props-excludes-external/main.svelte @@ -0,0 +1,9 @@ + + + +

some (unused) slotted content, to create an internal prop

+
\ No newline at end of file