From aedf69c1cf34cbb8c4706081e285d0a3d605bfd0 Mon Sep 17 00:00:00 2001 From: Maxime LUCE Date: Tue, 29 Jun 2021 03:43:52 +0200 Subject: [PATCH] Add compilation variables report option to allow getting all variables (even undeclared or internal) (#6192) * feat: add compilation variables report option * test: add full var report test * docs: document varsReport compile option --- site/content/docs/04-compile-time.md | 4 +- src/compiler/compile/Component.ts | 47 +++++++++++++------ src/compiler/compile/index.ts | 1 + src/compiler/interfaces.ts | 1 + .../vars/samples/vars-report-false/_config.js | 9 ++++ .../samples/vars-report-false/input.svelte | 5 ++ .../vars-report-full-noscript/_config.js | 19 ++++++++ .../vars-report-full-noscript/input.svelte | 1 + .../vars-report-full-script/_config.js | 31 ++++++++++++ .../vars-report-full-script/input.svelte | 5 ++ test/vars/samples/vars-report-full/_config.js | 19 ++++++++ .../samples/vars-report-full/input.svelte | 3 ++ 12 files changed, 129 insertions(+), 16 deletions(-) create mode 100644 test/vars/samples/vars-report-false/_config.js create mode 100644 test/vars/samples/vars-report-false/input.svelte create mode 100644 test/vars/samples/vars-report-full-noscript/_config.js create mode 100644 test/vars/samples/vars-report-full-noscript/input.svelte create mode 100644 test/vars/samples/vars-report-full-script/_config.js create mode 100644 test/vars/samples/vars-report-full-script/input.svelte create mode 100644 test/vars/samples/vars-report-full/_config.js create mode 100644 test/vars/samples/vars-report-full/input.svelte diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index 59a144d162..90f094067a 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -44,7 +44,8 @@ The following options can be passed to the compiler. None are required: | `filename` | string | `null` | `name` | string | `"Component"` | `format` | `"esm"` or `"cjs"` | `"esm"` -| `generate` | `"dom"` or `"ssr"` | `"dom"` +| `generate` | `"dom"` or `"ssr" or false` | `"dom"` +| `varsReport` | `"strict"` or `"full" or false` | `"strict"` | `dev` | boolean | `false` | `immutable` | boolean | `false` | `hydratable` | boolean | `false` @@ -66,6 +67,7 @@ The following options can be passed to the compiler. None are required: | `name` | `"Component"` | `string` that sets the name of the resulting JavaScript class (though the compiler will rename it if it would otherwise conflict with other variables in scope). It will normally be inferred from `filename`. | `format` | `"esm"` | If `"esm"`, creates a JavaScript module (with `import` and `export`). If `"cjs"`, creates a CommonJS module (with `require` and `module.exports`), which is useful in some server-side rendering situations or for testing. | `generate` | `"dom"` | If `"dom"`, Svelte emits a JavaScript class for mounting to the DOM. If `"ssr"`, Svelte emits an object with a `render` method suitable for server-side rendering. If `false`, no JavaScript or CSS is returned; just metadata. +| `varsReport` | `"strict"` | If `"strict"`, Svelte returns a variables report with only variables that are not globals nor internals. If `"full"`, Svelte returns a variables report with all detected variables. If `false`, no variables report is returned. | `dev` | `false` | If `true`, causes extra code to be added to components that will perform runtime checks and provide debugging information during development. | `immutable` | `false` | If `true`, tells the compiler that you promise not to mutate any objects. This allows it to be less conservative about checking whether values have changed. | `hydratable` | `false` | If `true` when generating DOM code, enables the `hydrate: true` runtime option, which allows a component to upgrade existing DOM rather than creating new DOM from scratch. When generating SSR code, this adds markers to `` elements so that hydration knows which to replace. diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index 155b64778b..e3738a8dba 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -183,9 +183,12 @@ export default class Component { this.stylesheet.warn_on_unused_selectors(this); } - add_var(variable: Var) { + add_var(variable: Var, add_to_lookup = true) { this.vars.push(variable); - this.var_lookup.set(variable.name, variable); + + if (add_to_lookup) { + this.var_lookup.set(variable.name, variable); + } } add_reference(name: string) { @@ -216,6 +219,10 @@ export default class Component { variable.subscribable = true; } } else { + if (this.compile_options.varsReport === 'full') { + this.add_var({ name, referenced: true }, false); + } + this.used_names.add(name); } } @@ -340,19 +347,7 @@ export default class Component { css, ast: this.original_ast, warnings: this.warnings, - vars: this.vars - .filter(v => !v.global && !v.internal) - .map(v => ({ - name: v.name, - export_name: v.export_name || null, - injected: v.injected || false, - module: v.module || false, - mutated: v.mutated || false, - reassigned: v.reassigned || false, - referenced: v.referenced || false, - writable: v.writable || false, - referenced_from_script: v.referenced_from_script || false - })), + vars: this.get_vars_report(), stats: this.stats.render() }; } @@ -402,6 +397,28 @@ export default class Component { }; } + get_vars_report(): Var[] { + const { compile_options, vars } = this; + + const vars_report = compile_options.varsReport === false + ? [] + : compile_options.varsReport === 'full' + ? vars + : vars.filter(v => !v.global && !v.internal); + + return vars_report.map(v => ({ + name: v.name, + export_name: v.export_name || null, + injected: v.injected || false, + module: v.module || false, + mutated: v.mutated || false, + reassigned: v.reassigned || false, + referenced: v.referenced || false, + writable: v.writable || false, + referenced_from_script: v.referenced_from_script || false + })); + } + error( pos: { start: number; diff --git a/src/compiler/compile/index.ts b/src/compiler/compile/index.ts index c9b594dbe3..e40ff37e92 100644 --- a/src/compiler/compile/index.ts +++ b/src/compiler/compile/index.ts @@ -14,6 +14,7 @@ const valid_options = [ 'filename', 'sourcemap', 'generate', + 'varsReport', 'outputFilename', 'cssOutputFilename', 'sveltePath', diff --git a/src/compiler/interfaces.ts b/src/compiler/interfaces.ts index a34f932a93..ce585b5b78 100644 --- a/src/compiler/interfaces.ts +++ b/src/compiler/interfaces.ts @@ -116,6 +116,7 @@ export interface CompileOptions { name?: string; filename?: string; generate?: 'dom' | 'ssr' | false; + varsReport?: 'full' | 'strict' | false; sourcemap?: object | string; outputFilename?: string; diff --git a/test/vars/samples/vars-report-false/_config.js b/test/vars/samples/vars-report-false/_config.js new file mode 100644 index 0000000000..f4709f09c8 --- /dev/null +++ b/test/vars/samples/vars-report-false/_config.js @@ -0,0 +1,9 @@ +export default { + options: { + varsReport: false + }, + + test(assert, vars) { + assert.deepEqual(vars, []); + } +}; diff --git a/test/vars/samples/vars-report-false/input.svelte b/test/vars/samples/vars-report-false/input.svelte new file mode 100644 index 0000000000..7583c99845 --- /dev/null +++ b/test/vars/samples/vars-report-false/input.svelte @@ -0,0 +1,5 @@ + + +{foo} \ No newline at end of file diff --git a/test/vars/samples/vars-report-full-noscript/_config.js b/test/vars/samples/vars-report-full-noscript/_config.js new file mode 100644 index 0000000000..9c39324518 --- /dev/null +++ b/test/vars/samples/vars-report-full-noscript/_config.js @@ -0,0 +1,19 @@ +export default { + options: { + varsReport: 'full' + }, + + test(assert, vars) { + assert.deepEqual(vars, [{ + name: 'foo', + export_name: null, + injected: false, + module: false, + mutated: false, + reassigned: false, + referenced: true, + referenced_from_script: false, + writable: false + }]); + } +}; diff --git a/test/vars/samples/vars-report-full-noscript/input.svelte b/test/vars/samples/vars-report-full-noscript/input.svelte new file mode 100644 index 0000000000..e076ac55f8 --- /dev/null +++ b/test/vars/samples/vars-report-full-noscript/input.svelte @@ -0,0 +1 @@ +{foo} \ No newline at end of file diff --git a/test/vars/samples/vars-report-full-script/_config.js b/test/vars/samples/vars-report-full-script/_config.js new file mode 100644 index 0000000000..2519dc5508 --- /dev/null +++ b/test/vars/samples/vars-report-full-script/_config.js @@ -0,0 +1,31 @@ +export default { + options: { + varsReport: 'full' + }, + + test(assert, vars) { + assert.deepEqual(vars, [ + { + name: 'foo', + export_name: 'foo', + injected: false, + module: false, + mutated: false, + reassigned: false, + referenced: true, + referenced_from_script: false, + writable: true + }, { + name: 'bar', + export_name: null, + injected: false, + module: false, + mutated: false, + reassigned: false, + referenced: true, + referenced_from_script: false, + writable: false + } + ]); + } +}; diff --git a/test/vars/samples/vars-report-full-script/input.svelte b/test/vars/samples/vars-report-full-script/input.svelte new file mode 100644 index 0000000000..11870584a6 --- /dev/null +++ b/test/vars/samples/vars-report-full-script/input.svelte @@ -0,0 +1,5 @@ + + +{foo} {bar} \ No newline at end of file diff --git a/test/vars/samples/vars-report-full/_config.js b/test/vars/samples/vars-report-full/_config.js new file mode 100644 index 0000000000..9c39324518 --- /dev/null +++ b/test/vars/samples/vars-report-full/_config.js @@ -0,0 +1,19 @@ +export default { + options: { + varsReport: 'full' + }, + + test(assert, vars) { + assert.deepEqual(vars, [{ + name: 'foo', + export_name: null, + injected: false, + module: false, + mutated: false, + reassigned: false, + referenced: true, + referenced_from_script: false, + writable: false + }]); + } +}; diff --git a/test/vars/samples/vars-report-full/input.svelte b/test/vars/samples/vars-report-full/input.svelte new file mode 100644 index 0000000000..0178466fe3 --- /dev/null +++ b/test/vars/samples/vars-report-full/input.svelte @@ -0,0 +1,3 @@ + + +{foo} \ No newline at end of file