diff --git a/CHANGELOG.md b/CHANGELOG.md index 9569b4ff7b..8ed9b5a3c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Svelte changelog +## Unreleased + +* Support `use:obj.method` as actions ([#3935](https://github.com/sveltejs/svelte/issues/3935)) +* Support `_` as numeric separator ([#5407](https://github.com/sveltejs/svelte/issues/5407)) +* Fix assignments to properties on store values ([#5412](https://github.com/sveltejs/svelte/issues/5412)) +* Support `import.meta` in template expressions ([#5422](https://github.com/sveltejs/svelte/issues/5422)) + ## 3.25.1 * Fix specificity of certain styles involving a child selector ([#4795](https://github.com/sveltejs/svelte/issues/4795)) diff --git a/package-lock.json b/package-lock.json index d1ec8d275f..2e2a95b362 100644 --- a/package-lock.json +++ b/package-lock.json @@ -315,9 +315,9 @@ "dev": true }, "acorn": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", - "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", "dev": true }, "acorn-globals": { diff --git a/package.json b/package.json index 20325b4fbf..7ebb41fdfb 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@types/node": "^8.10.53", "@typescript-eslint/eslint-plugin": "^3.0.2", "@typescript-eslint/parser": "^3.0.2", - "acorn": "^7.3.1", + "acorn": "^7.4.0", "agadoo": "^1.1.0", "c8": "^5.0.1", "code-red": "^0.1.3", diff --git a/src/compiler/compile/nodes/shared/Expression.ts b/src/compiler/compile/nodes/shared/Expression.ts index bbbc1b2f2d..834287bb63 100644 --- a/src/compiler/compile/nodes/shared/Expression.ts +++ b/src/compiler/compile/nodes/shared/Expression.ts @@ -64,6 +64,8 @@ export default class Expression { enter(node: any, parent: any, key: string) { // don't manipulate shorthand props twice if (key === 'value' && parent.shorthand) return; + // don't manipulate `import.meta`, `new.target` + if (node.type === 'MetaProperty') return this.skip(); if (map.has(node)) { scope = map.get(node); diff --git a/src/compiler/compile/render_dom/invalidate.ts b/src/compiler/compile/render_dom/invalidate.ts index c7d9759ccd..b045db079f 100644 --- a/src/compiler/compile/render_dom/invalidate.ts +++ b/src/compiler/compile/render_dom/invalidate.ts @@ -62,7 +62,7 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names: } let invalidate = is_store_value - ? x`@set_store_value(${head.name.slice(1)}, ${node}, ${extra_args})` + ? x`@set_store_value(${head.name.slice(1)}, ${node}, ${head.name})` : !main_execution_context ? x`$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})` : extra_args.length diff --git a/src/compiler/compile/render_dom/wrappers/shared/add_actions.ts b/src/compiler/compile/render_dom/wrappers/shared/add_actions.ts index 3d8c4fbbc0..6ca7de9a22 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/add_actions.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/add_actions.ts @@ -26,11 +26,19 @@ export function add_action(block: Block, target: string, action: Action) { block.add_variable(id); - const fn = block.renderer.reference(action.name); + const [obj, ...properties] = action.name.split('.'); - block.event_listeners.push( - x`@action_destroyer(${id} = ${fn}.call(null, ${target}, ${snippet}))` - ); + const fn = block.renderer.reference(obj); + + if (properties.length) { + block.event_listeners.push( + x`@action_destroyer(${id} = ${fn}.${properties.join('.')}(${target}, ${snippet}))` + ); + } else { + block.event_listeners.push( + x`@action_destroyer(${id} = ${fn}.call(null, ${target}, ${snippet}))` + ); + } if (dependencies && dependencies.length > 0) { let condition = x`${id} && @is_function(${id}.update)`; diff --git a/src/compiler/parse/acorn.ts b/src/compiler/parse/acorn.ts index d14721cdab..58031c1a1c 100644 --- a/src/compiler/parse/acorn.ts +++ b/src/compiler/parse/acorn.ts @@ -3,11 +3,12 @@ import * as code_red from 'code-red'; export const parse = (source: string): Node => code_red.parse(source, { sourceType: 'module', - ecmaVersion: 11, + ecmaVersion: 12, locations: true }); export const parse_expression_at = (source: string, index: number): Node => code_red.parseExpressionAt(source, index, { - ecmaVersion: 11, + sourceType: 'module', + ecmaVersion: 12, locations: true }); \ No newline at end of file diff --git a/test/js/samples/import-meta/expected.js b/test/js/samples/import-meta/expected.js new file mode 100644 index 0000000000..ba77398321 --- /dev/null +++ b/test/js/samples/import-meta/expected.js @@ -0,0 +1,53 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + detach, + init, + insert, + noop, + safe_not_equal, + space, + text +} from "svelte/internal"; + +function create_fragment(ctx) { + let t0; + let t1; + let t2_value = import.meta.url + ""; + let t2; + + return { + c() { + t0 = text(/*url*/ ctx[0]); + t1 = space(); + t2 = text(t2_value); + }, + m(target, anchor) { + insert(target, t0, anchor); + insert(target, t1, anchor); + insert(target, t2, anchor); + }, + p: noop, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(t0); + if (detaching) detach(t1); + if (detaching) detach(t2); + } + }; +} + +function instance($$self) { + const url = import.meta.url; + return [url]; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, {}); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/import-meta/input.svelte b/test/js/samples/import-meta/input.svelte new file mode 100644 index 0000000000..a5ce32dd77 --- /dev/null +++ b/test/js/samples/import-meta/input.svelte @@ -0,0 +1,6 @@ + + +{url} +{import.meta.url} diff --git a/test/runtime/samples/action-object/_config.js b/test/runtime/samples/action-object/_config.js new file mode 100644 index 0000000000..7fdc11af2b --- /dev/null +++ b/test/runtime/samples/action-object/_config.js @@ -0,0 +1,8 @@ +export default { + html: ` + + `, + async test({ assert, target, window }) { + assert.equal(target.querySelector('button').foo, 'bar1337'); + } +}; diff --git a/test/runtime/samples/action-object/main.svelte b/test/runtime/samples/action-object/main.svelte new file mode 100644 index 0000000000..f15e319e6f --- /dev/null +++ b/test/runtime/samples/action-object/main.svelte @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/test/runtime/samples/numeric-seperator/_config.js b/test/runtime/samples/numeric-seperator/_config.js new file mode 100644 index 0000000000..bc6d7c04f3 --- /dev/null +++ b/test/runtime/samples/numeric-seperator/_config.js @@ -0,0 +1,3 @@ +export default { + html: `2048 2048` +}; diff --git a/test/runtime/samples/numeric-seperator/main.svelte b/test/runtime/samples/numeric-seperator/main.svelte new file mode 100644 index 0000000000..e491b8a107 --- /dev/null +++ b/test/runtime/samples/numeric-seperator/main.svelte @@ -0,0 +1,5 @@ + + +{num} {2_048} \ No newline at end of file diff --git a/test/runtime/samples/store-assignment-updates-property/_config.js b/test/runtime/samples/store-assignment-updates-property/_config.js new file mode 100644 index 0000000000..65df38f9e4 --- /dev/null +++ b/test/runtime/samples/store-assignment-updates-property/_config.js @@ -0,0 +1,32 @@ +export default { + html: ` +
a: {"foo":3,"bar":2}
+b: {"foo":3}
+ + + `, + skip_if_ssr: true, + + async test({ assert, component, target, window }) { + const [btn1, btn2] = target.querySelectorAll('button'); + const click = new window.MouseEvent('click'); + + await btn1.dispatchEvent(click); + + assert.htmlEqual(target.innerHTML, ` +a: {"foo":4,"bar":2}
+b: {"foo":4,"baz":0}
+ + + `); + + await btn2.dispatchEvent(click); + + assert.htmlEqual(target.innerHTML, ` +a: {"foo":5,"bar":2}
+b: {"foo":5,"qux":0}
+ + + `); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/store-assignment-updates-property/main.svelte b/test/runtime/samples/store-assignment-updates-property/main.svelte new file mode 100644 index 0000000000..c3196a278c --- /dev/null +++ b/test/runtime/samples/store-assignment-updates-property/main.svelte @@ -0,0 +1,24 @@ + + +a: {JSON.stringify($a)}
+b: {JSON.stringify($b)}
+ +