Skip to content

Commit

Permalink
Merge pull request #2963 from sveltejs/gh-2612
Browse files Browse the repository at this point in the history
Import globals from internals
  • Loading branch information
Rich-Harris authored Jun 24, 2019
2 parents 2de0f1c + b801c67 commit 64c805b
Show file tree
Hide file tree
Showing 24 changed files with 152 additions and 80 deletions.
41 changes: 28 additions & 13 deletions src/compiler/compile/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ export default class Component {
reactive_declaration_nodes: Set<Node> = new Set();
has_reactive_assignments = false;
injected_reactive_declaration_vars: Set<string> = new Set();
helpers: Set<string> = new Set();
helpers: Map<string, string> = new Map();
globals: Map<string, string> = new Map();

indirect_dependencies: Map<string, Set<string>> = new Map();

Expand Down Expand Up @@ -233,8 +234,15 @@ export default class Component {
}

helper(name: string) {
this.helpers.add(name);
return this.alias(name);
const alias = this.alias(name)
this.helpers.set(name, alias);
return alias;
}

global(name: string) {
const alias = this.alias(name);
this.globals.set(name, alias);
return alias;
}

generate(result: string) {
Expand All @@ -251,23 +259,29 @@ export default class Component {
.replace(/__svelte:self__/g, this.name)
.replace(compile_options.generate === 'ssr' ? /(@+|#+)(\w*(?:-\w*)?)/g : /(@+)(\w*(?:-\w*)?)/g, (_match: string, sigil: string, name: string) => {
if (sigil === '@') {
if (internal_exports.has(name)) {
if (compile_options.dev && internal_exports.has(`${name}Dev`)) name = `${name}Dev`;
this.helpers.add(name);
if (name[0] === '_') {
return this.global(name.slice(1));
}

if (!internal_exports.has(name)) {
throw new Error(`compiler error: this shouldn't happen! generated code is trying to use inexistent internal '${name}'`);
}

if (compile_options.dev && internal_exports.has(`${name}Dev`)) {
name = `${name}Dev`;
}

return this.alias(name);
return this.helper(name);
}

return sigil.slice(1) + name;
});

const imported_helpers = Array.from(this.helpers)
.sort()
.map(name => {
const alias = this.alias(name);
return { name, alias };
});
const referenced_globals = Array.from(this.globals, ([name, alias]) => name !== alias && ({ name, alias })).filter(Boolean);
if (referenced_globals.length) {
this.helper('globals');
}
const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({ name, alias }));

const module = create_module(
result,
Expand All @@ -276,6 +290,7 @@ export default class Component {
banner,
compile_options.sveltePath,
imported_helpers,
referenced_globals,
this.imports,
this.vars.filter(variable => variable.module && variable.export_name).map(variable => ({
name: variable.name,
Expand Down
15 changes: 13 additions & 2 deletions src/compiler/compile/create_module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,18 @@ export default function create_module(
banner: string,
sveltePath = 'svelte',
helpers: Array<{ name: string; alias: string }>,
globals: Array<{ name: string; alias: string }>,
imports: Node[],
module_exports: Export[],
source: string
): string {
const internal_path = `${sveltePath}/internal`;

if (format === 'esm') {
return esm(code, name, banner, sveltePath, internal_path, helpers, imports, module_exports, source);
return esm(code, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports, source);
}

if (format === 'cjs') return cjs(code, name, banner, sveltePath, internal_path, helpers, imports, module_exports);
if (format === 'cjs') return cjs(code, name, banner, sveltePath, internal_path, helpers, globals, imports, module_exports);

throw new Error(`options.format is invalid (must be ${list(Object.keys(wrappers))})`);
}
Expand All @@ -45,13 +46,17 @@ function esm(
sveltePath: string,
internal_path: string,
helpers: Array<{ name: string; alias: string }>,
globals: Array<{ name: string; alias: string }>,
imports: Node[],
module_exports: Export[],
source: string
) {
const internal_imports = helpers.length > 0 && (
`import ${stringify_props(helpers.map(h => h.name === h.alias ? h.name : `${h.name} as ${h.alias}`).sort())} from ${JSON.stringify(internal_path)};`
);
const internal_globals = globals.length > 0 && (
`const ${stringify_props(globals.map(g => `${g.name}: ${g.alias}`).sort())} = ${helpers.find(({ name }) => name === 'globals').alias};`
);

const user_imports = imports.length > 0 && (
imports
Expand All @@ -70,6 +75,7 @@ function esm(
return deindent`
${banner}
${internal_imports}
${internal_globals}
${user_imports}
${code}
Expand All @@ -85,6 +91,7 @@ function cjs(
sveltePath: string,
internal_path: string,
helpers: Array<{ name: string; alias: string }>,
globals: Array<{ name: string; alias: string }>,
imports: Node[],
module_exports: Export[]
) {
Expand All @@ -93,6 +100,9 @@ function cjs(
const internal_imports = helpers.length > 0 && (
`const ${stringify_props(declarations)} = require(${JSON.stringify(internal_path)});\n`
);
const internal_globals = globals.length > 0 && (
`const ${stringify_props(globals.map(g => `${g.name}: ${g.alias}`).sort())} = ${helpers.find(({ name }) => name === 'globals').alias};`
);

const requires = imports.map(node => {
let lhs;
Expand Down Expand Up @@ -127,6 +137,7 @@ function cjs(
"use strict";
${internal_imports}
${internal_globals}
${requires}
${code}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/compile/render-dom/Block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export default class Block {

if (parent_node) {
this.builders.mount.add_line(`@append(${parent_node}, ${name});`);
if (parent_node === 'document.head' && !no_detach) this.builders.destroy.add_line(`@detach(${name});`);
if (parent_node === '@_document.head' && !no_detach) this.builders.destroy.add_line(`@detach(${name});`);
} else {
this.builders.mount.add_line(`@insert(#target, ${name}, anchor);`);
if (!no_detach) this.builders.destroy.add_conditional('detaching', `@detach(${name});`);
Expand Down
24 changes: 13 additions & 11 deletions src/compiler/compile/render-dom/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ export default function dom(
`${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */` :
css.code, { only_escape_at_symbol: true });

const add_css = component.get_unique_name('add_css');

if (styles && component.compile_options.css !== false && !options.customElement) {
builder.add_block(deindent`
function @add_css() {
function ${add_css}() {
var style = @element("style");
style.id = '${component.stylesheet.id}-style';
style.textContent = ${styles};
@append(document.head, style);
@append(@_document.head, style);
}
`);
}
Expand All @@ -57,7 +59,7 @@ export default function dom(

if (options.dev && !options.hydratable) {
block.builders.claim.add_line(
'throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");'
'throw new @_Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");'
);
}

Expand Down Expand Up @@ -106,7 +108,7 @@ export default function dom(
} else if (component.compile_options.dev) {
body.push(deindent`
get ${x.export_name}() {
throw new Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
}
`);
}
Expand All @@ -122,14 +124,14 @@ export default function dom(
} else if (component.compile_options.dev) {
body.push(deindent`
set ${x.export_name}(value) {
throw new Error("<${component.tag}>: Cannot set read-only property '${x.export_name}'");
throw new @_Error("<${component.tag}>: Cannot set read-only property '${x.export_name}'");
}
`);
}
} else if (component.compile_options.dev) {
body.push(deindent`
set ${x.export_name}(value) {
throw new Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
throw new @_Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
}
`);
}
Expand All @@ -145,7 +147,7 @@ export default function dom(
const props = ${options.customElement ? `this.attributes` : `options.props || {}`};
${expected.map(prop => deindent`
if (ctx.${prop.name} === undefined && !('${prop.export_name}' in props)) {
console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'");
@_console.warn("<${component.tag}> was created without expected prop '${prop.export_name}'");
}`)}
`;
}
Expand Down Expand Up @@ -402,8 +404,8 @@ export default function dom(
if (component.compile_options.dev && !component.var_lookup.has('$$props') && writable_props.length) {
unknown_props_check = deindent`
const writable_props = [${writable_props.map(prop => `'${prop.export_name}'`).join(', ')}];
Object.keys($$props).forEach(key => {
if (!writable_props.includes(key) && !key.startsWith('$$')) console.warn(\`<${component.tag}> was created with unknown prop '\${key}'\`);
@_Object.keys($$props).forEach(key => {
if (!writable_props.includes(key) && !key.startsWith('$$')) @_console.warn(\`<${component.tag}> was created with unknown prop '\${key}'\`);
});
`;
}
Expand Down Expand Up @@ -481,7 +483,7 @@ export default function dom(

if (component.tag != null) {
builder.add_block(deindent`
customElements.define("${component.tag}", ${name});
@_customElements.define("${component.tag}", ${name});
`);
}
} else {
Expand All @@ -491,7 +493,7 @@ export default function dom(
class ${name} extends @${superclass} {
constructor(options) {
super(${options.dev && `options`});
${should_add_css && `if (!document.getElementById("${component.stylesheet.id}-style")) @add_css();`}
${should_add_css && `if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
@init(this, options, ${definition}, create_fragment, ${not_equal}, ${prop_names});
${dev_props_check}
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/compile/render-dom/wrappers/AwaitBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export default class AwaitBlockWrapper extends Wrapper {
this.catch.block.name && `catch: ${this.catch.block.name}`,
this.then.block.name && `value: '${this.node.value}'`,
this.catch.block.name && `error: '${this.node.error}'`,
this.pending.block.has_outro_method && `blocks: Array(3)`
this.pending.block.has_outro_method && `blocks: [,,,]`
].filter(Boolean);

block.builders.init.add_block(deindent`
Expand Down Expand Up @@ -230,4 +230,4 @@ export default class AwaitBlockWrapper extends Wrapper {
branch.fragment.render(branch.block, null, 'nodes');
});
}
}
}
4 changes: 2 additions & 2 deletions src/compiler/compile/render-dom/wrappers/Body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ export default class BodyWrapper extends Wrapper {
const snippet = handler.render(block);

block.builders.init.add_block(deindent`
document.body.addEventListener("${handler.name}", ${snippet});
@_document.body.addEventListener("${handler.name}", ${snippet});
`);

block.builders.destroy.add_block(deindent`
document.body.removeEventListener("${handler.name}", ${snippet});
@_document.body.removeEventListener("${handler.name}", ${snippet});
`);
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/compile/render-dom/wrappers/DebugTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ export default class DebugTagWrapper extends Wrapper {
block.builders.update.add_block(deindent`
if (${condition}) {
const { ${ctx_identifiers} } = ctx;
console.${log}({ ${logged_identifiers} });
@_console.${log}({ ${logged_identifiers} });
debugger;
}
`);

block.builders.create.add_block(deindent`
{
const { ${ctx_identifiers} } = ctx;
console.${log}({ ${logged_identifiers} });
@_console.${log}({ ${logged_identifiers} });
debugger;
}
`);
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/compile/render-dom/wrappers/EachBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export default class EachBlockWrapper extends Wrapper {

renderer.blocks.push(deindent`
function ${this.vars.get_each_context}(ctx, list, i) {
const child_ctx = Object.create(ctx);
const child_ctx = @_Object.create(ctx);
${this.context_props}
return child_ctx;
}
Expand Down Expand Up @@ -296,7 +296,7 @@ export default class EachBlockWrapper extends Wrapper {
const lookup = block.get_unique_name(`${this.var}_lookup`);

block.add_variable(iterations, '[]');
block.add_variable(lookup, `new Map()`);
block.add_variable(lookup, `new @_Map()`);

if (this.fragment.nodes[0].is_dom_node()) {
this.block.first = this.fragment.nodes[0].var;
Expand Down Expand Up @@ -498,7 +498,7 @@ export default class EachBlockWrapper extends Wrapper {

if (this.block.has_outros) {
block.builders.outro.add_block(deindent`
${iterations} = ${iterations}.filter(Boolean);
${iterations} = ${iterations}.filter(@_Boolean);
for (let #i = 0; #i < ${view_length}; #i += 1) @transition_out(${iterations}[#i]);`
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export default class BindingWrapper {
case 'currentTime':
case 'playbackRate':
case 'volume':
update_conditions.push(`!isNaN(${this.snippet})`);
update_conditions.push(`!@_isNaN(${this.snippet})`);
break;

case 'paused':
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/compile/render-dom/wrappers/Element/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export default class ElementWrapper extends Wrapper {
`@append(${parent_node}, ${node});`
);

if (parent_node === 'document.head') {
if (parent_node === '@_document.head') {
block.builders.destroy.add_line(`@detach(${node});`);
}
} else {
Expand Down Expand Up @@ -381,7 +381,7 @@ export default class ElementWrapper extends Wrapper {
}

if (namespace) {
return `document.createElementNS("${namespace}", "${name}")`;
return `@_document.createElementNS("${namespace}", "${name}")`;
}

return `@element("${name}")`;
Expand Down Expand Up @@ -467,7 +467,7 @@ export default class ElementWrapper extends Wrapper {
block.builders.init.add_block(deindent`
function ${handler}() {
${animation_frame && deindent`
cancelAnimationFrame(${animation_frame});
@_cancelAnimationFrame(${animation_frame});
if (!${this.var}.paused) ${animation_frame} = @raf(${handler});`}
${needs_lock && `${lock} = true;`}
ctx.${handler}.call(${this.var}${contextual_dependencies.size > 0 ? ', ctx' : ''});
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/compile/render-dom/wrappers/Head.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ export default class HeadWrapper extends Wrapper {
}

render(block: Block, _parent_node: string, _parent_nodes: string) {
this.fragment.render(block, 'document.head', 'nodes');
this.fragment.render(block, '@_document.head', 'nodes');
}
}
2 changes: 1 addition & 1 deletion src/compiler/compile/render-dom/wrappers/IfBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export default class IfBlockWrapper extends Wrapper {

const vars = { name, anchor, if_name, has_else, has_transitions };

const detaching = (parent_node && parent_node !== 'document.head') ? '' : 'detaching';
const detaching = (parent_node && parent_node !== '@_document.head') ? '' : 'detaching';

if (this.node.else) {
if (has_outros) {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/compile/render-dom/wrappers/RawMustacheTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default class RawMustacheTagWrapper extends Tag {
render(block: Block, parent_node: string, parent_nodes: string) {
const name = this.var;

const in_head = parent_node === 'document.head';
const in_head = parent_node === '@_document.head';
const needs_anchors = !parent_node || in_head;

// if in head always needs anchors
Expand Down
Loading

0 comments on commit 64c805b

Please sign in to comment.