From 3d36e8271626a2ac02368c5be1c733b886632127 Mon Sep 17 00:00:00 2001 From: Dylan Piercey Date: Wed, 2 Nov 2022 12:04:24 -0700 Subject: [PATCH] feat: function dependencies now include member expressions, allow using top level input, convert to new default attribute name --- .changeset/healthy-ravens-wink.md | 5 + .changeset/popular-poems-appear.md | 5 + .changeset/shiny-points-reflect.md | 5 + package-lock.json | 50 ++++---- package.json | 6 +- src/__tests__/fixtures/effect/index.test.ts | 21 ++++ .../templates/input-member-expression.marko | 8 ++ .../fixtures/get-and-set/index.test.ts | 18 +-- .../templates/assign-to-mutable-set.marko | 4 +- .../assign-to-nested-mutable-set.marko | 4 +- .../templates/error-set-spread-attr.marko | 2 +- .../let/templates/with-default-change.marko | 2 +- .../misc/components/invoke-on-mount.marko | 2 +- .../fixtures/misc/components/invoke.marko | 2 +- .../fixtures/misc/components/repeat.marko | 2 +- .../misc/feature-detect/index.test.ts | 5 - .../components/read-write-clamped.marko | 2 +- .../templates/components/read-write.marko | 2 +- src/components/const/marko-tag.json | 2 +- src/components/effect/marko-tag.json | 2 +- src/components/get/index.marko | 10 +- src/components/get/marko-tag.json | 2 +- src/components/let/marko-tag.json | 4 +- src/components/return/index-browser.ts | 4 +- src/components/return/marko-tag.json | 4 +- src/components/set/marko-tag.json | 4 +- src/transform/cached-function/transform.ts | 114 ++++++++++++------ 27 files changed, 182 insertions(+), 109 deletions(-) create mode 100644 .changeset/healthy-ravens-wink.md create mode 100644 .changeset/popular-poems-appear.md create mode 100644 .changeset/shiny-points-reflect.md create mode 100644 src/__tests__/fixtures/effect/templates/input-member-expression.marko diff --git a/.changeset/healthy-ravens-wink.md b/.changeset/healthy-ravens-wink.md new file mode 100644 index 0000000..013da0e --- /dev/null +++ b/.changeset/healthy-ravens-wink.md @@ -0,0 +1,5 @@ +--- +"@marko/tags-api-preview": minor +--- + +Allow using top level input rather than just tag. diff --git a/.changeset/popular-poems-appear.md b/.changeset/popular-poems-appear.md new file mode 100644 index 0000000..79e8305 --- /dev/null +++ b/.changeset/popular-poems-appear.md @@ -0,0 +1,5 @@ +--- +"@marko/tags-api-preview": minor +--- + +Switch to new default attribute name (value instead of default). diff --git a/.changeset/shiny-points-reflect.md b/.changeset/shiny-points-reflect.md new file mode 100644 index 0000000..1ab6f2e --- /dev/null +++ b/.changeset/shiny-points-reflect.md @@ -0,0 +1,5 @@ +--- +"@marko/tags-api-preview": minor +--- + +Member expressions now are accounted for when determining function dependencies. diff --git a/package-lock.json b/package-lock.json index d6a091d..1fe6455 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ }, "devDependencies": { "@changesets/cli": "^2.25.0", - "@marko/compiler": "^5.22.9", + "@marko/compiler": "^5.23.0", "@marko/fixture-snapshots": "^2.1.7", "@marko/testing-library": "^6.1.2", "@testing-library/user-event": "^13.5.0", @@ -41,7 +41,7 @@ "jsdom": "^20.0.1", "jsdom-context-require": "^4.0.6", "lint-staged": "^13.0.3", - "marko": "^5.21.10", + "marko": "^5.22.0", "memfs": "^3.4.7", "mocha": "^10.1.0", "nyc": "^15.1.0", @@ -53,7 +53,7 @@ "unionfs": "^4.4.0" }, "peerDependencies": { - "marko": "<= 5.21.11" + "marko": "> 5.21.11" } }, "node_modules/@ampproject/remapping": { @@ -1098,9 +1098,9 @@ } }, "node_modules/@marko/compiler": { - "version": "5.22.9", - "resolved": "https://registry.npmjs.org/@marko/compiler/-/compiler-5.22.9.tgz", - "integrity": "sha512-03T5nOkS/VA1jUYWfTMBhbsfUSenCoJ590rzuTDl/9EUp+ZqOmiLvQGmPxvFZA4MQRXQ4ZJGcjOlYQ1427Lhxw==", + "version": "5.23.0", + "resolved": "https://registry.npmjs.org/@marko/compiler/-/compiler-5.23.0.tgz", + "integrity": "sha512-bZp4pHREL6IRe7U315XiVIms01k6WxjIvksXvcKnMhREH2ozN6HNotdBNNriP6NtZun1oALLGeoUwVHZXX/Pfg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.16.0", @@ -1265,9 +1265,9 @@ } }, "node_modules/@marko/translator-default": { - "version": "5.21.7", - "resolved": "https://registry.npmjs.org/@marko/translator-default/-/translator-default-5.21.7.tgz", - "integrity": "sha512-qSGC3vHA9y3Rcwi56JuusLxCBjUZoZVTfThwtuMt8NwVhRtRXY3A1vdC1eiDNAlfU4SKhiEqZo5xcSKQOq2dEA==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/@marko/translator-default/-/translator-default-5.22.0.tgz", + "integrity": "sha512-Zbl5rQRL7116d47EuqKU80lzNSvN337jhLd0gBrrpNQ1BFYDgImnSdS0kvlO2TkBaXD7I8CRgkNsdBMhgU4UOw==", "dev": true, "dependencies": { "@babel/runtime": "^7.16.0", @@ -6376,13 +6376,13 @@ } }, "node_modules/marko": { - "version": "5.21.10", - "resolved": "https://registry.npmjs.org/marko/-/marko-5.21.10.tgz", - "integrity": "sha512-/6owwIKwDxvhPWYrw/DbMpWO5kWvx2FtJfiXamnukcwNdF874qO94fE6GKwv53sXyRuvIaQt9a+1Iy9m32OC7g==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/marko/-/marko-5.22.0.tgz", + "integrity": "sha512-8hkiyrz2BSWVsnP0ZPy7VSDQPDHXStbFJ/tecwaLlMlt5unb0F0/M8nAc7bu2Fxx1xEr+FY4q/g4Y+vDrUO5Kw==", "dev": true, "dependencies": { - "@marko/compiler": "^5.22.9", - "@marko/translator-default": "^5.21.7", + "@marko/compiler": "^5.23.0", + "@marko/translator-default": "^5.22.0", "app-module-path": "^2.2.0", "argly": "^1.2.0", "browser-refresh-client": "1.1.4", @@ -10471,9 +10471,9 @@ } }, "@marko/compiler": { - "version": "5.22.9", - "resolved": "https://registry.npmjs.org/@marko/compiler/-/compiler-5.22.9.tgz", - "integrity": "sha512-03T5nOkS/VA1jUYWfTMBhbsfUSenCoJ590rzuTDl/9EUp+ZqOmiLvQGmPxvFZA4MQRXQ4ZJGcjOlYQ1427Lhxw==", + "version": "5.23.0", + "resolved": "https://registry.npmjs.org/@marko/compiler/-/compiler-5.23.0.tgz", + "integrity": "sha512-bZp4pHREL6IRe7U315XiVIms01k6WxjIvksXvcKnMhREH2ozN6HNotdBNNriP6NtZun1oALLGeoUwVHZXX/Pfg==", "dev": true, "requires": { "@babel/code-frame": "^7.16.0", @@ -10609,9 +10609,9 @@ } }, "@marko/translator-default": { - "version": "5.21.7", - "resolved": "https://registry.npmjs.org/@marko/translator-default/-/translator-default-5.21.7.tgz", - "integrity": "sha512-qSGC3vHA9y3Rcwi56JuusLxCBjUZoZVTfThwtuMt8NwVhRtRXY3A1vdC1eiDNAlfU4SKhiEqZo5xcSKQOq2dEA==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/@marko/translator-default/-/translator-default-5.22.0.tgz", + "integrity": "sha512-Zbl5rQRL7116d47EuqKU80lzNSvN337jhLd0gBrrpNQ1BFYDgImnSdS0kvlO2TkBaXD7I8CRgkNsdBMhgU4UOw==", "dev": true, "requires": { "@babel/runtime": "^7.16.0", @@ -14346,13 +14346,13 @@ "dev": true }, "marko": { - "version": "5.21.10", - "resolved": "https://registry.npmjs.org/marko/-/marko-5.21.10.tgz", - "integrity": "sha512-/6owwIKwDxvhPWYrw/DbMpWO5kWvx2FtJfiXamnukcwNdF874qO94fE6GKwv53sXyRuvIaQt9a+1Iy9m32OC7g==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/marko/-/marko-5.22.0.tgz", + "integrity": "sha512-8hkiyrz2BSWVsnP0ZPy7VSDQPDHXStbFJ/tecwaLlMlt5unb0F0/M8nAc7bu2Fxx1xEr+FY4q/g4Y+vDrUO5Kw==", "dev": true, "requires": { - "@marko/compiler": "^5.22.9", - "@marko/translator-default": "^5.21.7", + "@marko/compiler": "^5.23.0", + "@marko/translator-default": "^5.22.0", "app-module-path": "^2.2.0", "argly": "^1.2.0", "browser-refresh-client": "1.1.4", diff --git a/package.json b/package.json index a9d1a7e..07005f5 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ }, "devDependencies": { "@changesets/cli": "^2.25.0", - "@marko/compiler": "^5.22.9", + "@marko/compiler": "^5.23.0", "@marko/fixture-snapshots": "^2.1.7", "@marko/testing-library": "^6.1.2", "@testing-library/user-event": "^13.5.0", @@ -37,7 +37,7 @@ "jsdom": "^20.0.1", "jsdom-context-require": "^4.0.6", "lint-staged": "^13.0.3", - "marko": "^5.21.10", + "marko": "^5.22.0", "memfs": "^3.4.7", "mocha": "^10.1.0", "nyc": "^15.1.0", @@ -64,7 +64,7 @@ "license": "MIT", "main": "marko.json", "peerDependencies": { - "marko": "<= 5.21.11" + "marko": ">= 5.23.0" }, "repository": { "type": "git", diff --git a/src/__tests__/fixtures/effect/index.test.ts b/src/__tests__/fixtures/effect/index.test.ts index d3ffe4f..d6977d0 100644 --- a/src/__tests__/fixtures/effect/index.test.ts +++ b/src/__tests__/fixtures/effect/index.test.ts @@ -31,6 +31,27 @@ describe( ]) ); +describe( + " input member expression", + fixture("./templates/input-member-expression.marko", [ + { onCount, other: "other1", value: { a: 1, b: 2 } }, + async ({ expect, rerender }) => { + expect(onCount).calledOnceWith(2); + resetHistory(); + + await rerender({ onCount, other: "other2", value: { a: 1, b: 2 } }); + expect(onCount).has.not.been.called; + + await rerender({ onCount, other: "other2", value: { a: 3, b: 2 } }); + expect(onCount).has.not.been.called; + + await rerender({ onCount, other: "other2", value: { a: 3, b: 4 } }); + expect(onCount).calledOnceWith(4); + resetHistory(); + }, + ]) +); + describe( " no deps", fixture("./templates/no-deps.marko", [ diff --git a/src/__tests__/fixtures/effect/templates/input-member-expression.marko b/src/__tests__/fixtures/effect/templates/input-member-expression.marko new file mode 100644 index 0000000..11158be --- /dev/null +++ b/src/__tests__/fixtures/effect/templates/input-member-expression.marko @@ -0,0 +1,8 @@ + + ${input.other} + ${input.value.a} + + + { + input.onCount(input.value.b); +})/> diff --git a/src/__tests__/fixtures/get-and-set/index.test.ts b/src/__tests__/fixtures/get-and-set/index.test.ts index 87f85eb..c6b5606 100644 --- a/src/__tests__/fixtures/get-and-set/index.test.ts +++ b/src/__tests__/fixtures/get-and-set/index.test.ts @@ -1,7 +1,7 @@ import { spy, resetHistory } from "sinon"; import fixture from "../../fixture"; -const defaultChange = spy(); +const valueChange = spy(); describe( " & self reference", @@ -20,16 +20,16 @@ describe( describe( " & assign to mutable set", fixture("./templates/assign-to-mutable-set.marko", [ - { defaultChange }, + { valueChange }, async ({ expect, screen, rerender, fireEvent }) => { - expect(defaultChange).has.not.been.called; + expect(valueChange).has.not.been.called; await fireEvent.click(screen.getByText("increment")); - expect(defaultChange).calledOnceWith(2); + expect(valueChange).calledOnceWith(2); resetHistory(); await rerender(); - expect(defaultChange).has.not.been.called; + expect(valueChange).has.not.been.called; }, ]) ); @@ -37,16 +37,16 @@ describe( describe( " & assign to nested mutable set", fixture("./templates/assign-to-nested-mutable-set.marko", [ - { defaultChange }, + { valueChange }, async ({ expect, screen, rerender, fireEvent }) => { - expect(defaultChange).has.not.been.called; + expect(valueChange).has.not.been.called; await fireEvent.click(screen.getByText("increment")); - expect(defaultChange).calledOnceWith(2); + expect(valueChange).calledOnceWith(2); resetHistory(); await rerender(); - expect(defaultChange).has.not.been.called; + expect(valueChange).has.not.been.called; }, ]) ); diff --git a/src/__tests__/fixtures/get-and-set/templates/assign-to-mutable-set.marko b/src/__tests__/fixtures/get-and-set/templates/assign-to-mutable-set.marko index bafefac..e615e75 100644 --- a/src/__tests__/fixtures/get-and-set/templates/assign-to-mutable-set.marko +++ b/src/__tests__/fixtures/get-and-set/templates/assign-to-mutable-set.marko @@ -1,5 +1,5 @@ - - + +
${val}
diff --git a/src/__tests__/fixtures/get-and-set/templates/assign-to-nested-mutable-set.marko b/src/__tests__/fixtures/get-and-set/templates/assign-to-nested-mutable-set.marko index c42577d..168b8a1 100644 --- a/src/__tests__/fixtures/get-and-set/templates/assign-to-nested-mutable-set.marko +++ b/src/__tests__/fixtures/get-and-set/templates/assign-to-nested-mutable-set.marko @@ -1,5 +1,5 @@ - - + +
${x}
diff --git a/src/__tests__/fixtures/get-and-set/templates/error-set-spread-attr.marko b/src/__tests__/fixtures/get-and-set/templates/error-set-spread-attr.marko index 49eaf53..a0c3865 100644 --- a/src/__tests__/fixtures/get-and-set/templates/error-set-spread-attr.marko +++ b/src/__tests__/fixtures/get-and-set/templates/error-set-spread-attr.marko @@ -1,4 +1,4 @@ - +
diff --git a/src/__tests__/fixtures/let/templates/with-default-change.marko b/src/__tests__/fixtures/let/templates/with-default-change.marko index 02b2b33..1b6679f 100644 --- a/src/__tests__/fixtures/let/templates/with-default-change.marko +++ b/src/__tests__/fixtures/let/templates/with-default-change.marko @@ -1,5 +1,5 @@ - +
${count}
diff --git a/src/__tests__/fixtures/misc/components/invoke-on-mount.marko b/src/__tests__/fixtures/misc/components/invoke-on-mount.marko index 60f032f..c027f66 100644 --- a/src/__tests__/fixtures/misc/components/invoke-on-mount.marko +++ b/src/__tests__/fixtures/misc/components/invoke-on-mount.marko @@ -1,2 +1,2 @@ - + diff --git a/src/__tests__/fixtures/misc/components/invoke.marko b/src/__tests__/fixtures/misc/components/invoke.marko index 063ec3c..b0363c4 100644 --- a/src/__tests__/fixtures/misc/components/invoke.marko +++ b/src/__tests__/fixtures/misc/components/invoke.marko @@ -1,2 +1,2 @@ - + diff --git a/src/__tests__/fixtures/misc/components/repeat.marko b/src/__tests__/fixtures/misc/components/repeat.marko index 07a0671..34c3406 100644 --- a/src/__tests__/fixtures/misc/components/repeat.marko +++ b/src/__tests__/fixtures/misc/components/repeat.marko @@ -1,4 +1,4 @@ - + <${renderBody}=[i]/> diff --git a/src/__tests__/fixtures/misc/feature-detect/index.test.ts b/src/__tests__/fixtures/misc/feature-detect/index.test.ts index b7a0c1a..534fa10 100644 --- a/src/__tests__/fixtures/misc/feature-detect/index.test.ts +++ b/src/__tests__/fixtures/misc/feature-detect/index.test.ts @@ -48,11 +48,6 @@ describe("misc feature detect", () => { fixture("./templates/error-feature-detect-reference-component.marko") ); - describe( - "error reference input", - fixture("./templates/error-feature-detect-reference-input.marko") - ); - describe( "error reference out", fixture("./templates/error-feature-detect-reference-out.marko") diff --git a/src/__tests__/fixtures/return/templates/components/read-write-clamped.marko b/src/__tests__/fixtures/return/templates/components/read-write-clamped.marko index fc0ca4b..b1711ac 100644 --- a/src/__tests__/fixtures/return/templates/components/read-write-clamped.marko +++ b/src/__tests__/fixtures/return/templates/components/read-write-clamped.marko @@ -1,3 +1,3 @@ - x = Math.min(v, max))/> + x = Math.min(v, max))/> diff --git a/src/__tests__/fixtures/return/templates/components/read-write.marko b/src/__tests__/fixtures/return/templates/components/read-write.marko index 1e50352..4469f17 100644 --- a/src/__tests__/fixtures/return/templates/components/read-write.marko +++ b/src/__tests__/fixtures/return/templates/components/read-write.marko @@ -1,2 +1,2 @@ - x = v)/> + x = v)/> diff --git a/src/components/const/marko-tag.json b/src/components/const/marko-tag.json index a03168e..6862dbc 100644 --- a/src/components/const/marko-tag.json +++ b/src/components/const/marko-tag.json @@ -1,6 +1,6 @@ { "translate": "./translate", - "@default": { + "@value": { "type": "expression", "required": true, "autocomplete": [ diff --git a/src/components/effect/marko-tag.json b/src/components/effect/marko-tag.json index d1df82f..cf10980 100644 --- a/src/components/effect/marko-tag.json +++ b/src/components/effect/marko-tag.json @@ -1,6 +1,6 @@ { "translate": "./translate", - "@default": { + "@value": { "type": "expression", "required": true, "autocomplete": [ diff --git a/src/components/get/index.marko b/src/components/get/index.marko index 2682144..fa7384f 100644 --- a/src/components/get/index.marko +++ b/src/components/get/index.marko @@ -8,11 +8,11 @@ class { this.sync = this.sync.bind(this); } onInput(input, out) { - var from = input.default; + var from = input.value; if (!from || !from.render) { throw new Error( - "Invalid component constructor provided as 'default' attribute. Got: " + + "Invalid component constructor provided as 'value' attribute. Got: " + from ); } @@ -38,8 +38,8 @@ class { var prevData = this.data; this.data = this.provider.input; if ( - this.data.default !== prevData.default || - this.data.defaultChange !== prevData.defaultChange + this.data.value !== prevData.value || + this.data.valueChange !== prevData.valueChange ) { this.forceUpdate(); this.update(); @@ -48,4 +48,4 @@ class { } $ var data = component.data || {}; -<${input.renderBody}(data.default, data.defaultChange)/> +<${input.renderBody}(data.value, data.valueChange)/> diff --git a/src/components/get/marko-tag.json b/src/components/get/marko-tag.json index 8428c30..af66c2a 100644 --- a/src/components/get/marko-tag.json +++ b/src/components/get/marko-tag.json @@ -2,7 +2,7 @@ "template": "./index.marko", "transform": "./transform", "translate": "./translate", - "@default": { + "@value": { "type": "expression", "required": true, "autocomplete": [ diff --git a/src/components/let/marko-tag.json b/src/components/let/marko-tag.json index 2428cce..a683afe 100644 --- a/src/components/let/marko-tag.json +++ b/src/components/let/marko-tag.json @@ -1,6 +1,6 @@ { "translate": "./translate", - "@default": { + "@value": { "type": "expression", "required": true, "autocomplete": [ @@ -9,7 +9,7 @@ } ] }, - "@defaultChange": { + "@valueChange": { "type": "expression", "autocomplete": [ { diff --git a/src/components/return/index-browser.ts b/src/components/return/index-browser.ts index c347576..d1fd7b7 100644 --- a/src/components/return/index-browser.ts +++ b/src/components/return/index-browser.ts @@ -43,8 +43,8 @@ function createReturn(component: Component) { if (write) { if ( curValue && - (curValue.default !== newVal!.default || - curValue.defaultChange !== newVal!.defaultChange) + (curValue.value !== newVal!.value || + curValue.valueChange !== newVal!.valueChange) ) { component.forceUpdate(); } diff --git a/src/components/return/marko-tag.json b/src/components/return/marko-tag.json index bdb530e..c9dda1f 100644 --- a/src/components/return/marko-tag.json +++ b/src/components/return/marko-tag.json @@ -1,6 +1,6 @@ { "translate": "./translate", - "@default": { + "@value": { "type": "expression", "required": true, "autocomplete": [ @@ -9,7 +9,7 @@ } ] }, - "@defaultChange": { + "@valueChange": { "type": "expression", "autocomplete": [ { diff --git a/src/components/set/marko-tag.json b/src/components/set/marko-tag.json index 729b2fe..1379419 100644 --- a/src/components/set/marko-tag.json +++ b/src/components/set/marko-tag.json @@ -1,7 +1,7 @@ { "template": "./index.marko", "translate": "./translate", - "@default": { + "@value": { "type": "expression", "required": true, "autocomplete": [ @@ -10,7 +10,7 @@ } ] }, - "@defaultChange": { + "@valueChange": { "type": "expression", "autocomplete": [ { diff --git a/src/transform/cached-function/transform.ts b/src/transform/cached-function/transform.ts index 449a591..1bf0475 100644 --- a/src/transform/cached-function/transform.ts +++ b/src/transform/cached-function/transform.ts @@ -1,52 +1,61 @@ import { isNativeTag, isDynamicTag } from "@marko/babel-utils"; import { types as t } from "@marko/compiler"; import { importRuntimeNamed } from "../../util/import-runtime"; -import isCoreTag from "../../util/is-core-tag"; -import getAttr from "../../util/get-attr"; import isApi from "../../util/is-api"; import { ensureLifecycle } from "../wrapper-component"; -type DepsVisitorState = - | { root: t.NodePath; shallow?: undefined; deps?: Set } - | { root: t.NodePath; shallow: true; deps?: true }; + +interface Deps { + [x: string]: Deps | true; +} +interface DepsVisitorState { + parentTag: t.NodePath; + rootFn: t.NodePath; + deps?: Deps; +} const depsVisitor = { Function(fn, state) { - if (fn === state.root) fn.skip(); + if (fn === state.rootFn) fn.skip(); }, ReferencedIdentifier: ((identifier, state) => { - const { name } = identifier.node; + let { name } = identifier.node; const binding = identifier.scope.getBinding(name); - if (binding) { - const bindingTag = binding.path; - if ( - bindingTag.isMarkoTag() && - !(isNativeTag(bindingTag) || isDynamicTag(bindingTag)) - ) { - let isDep = false; + if ( + binding + ? binding.path.isMarkoTag() && + !( + binding.path === state.parentTag || + isNativeTag(binding.path) || + isDynamicTag(binding.path) + ) + : name === "input" + ) { + let deps = state.deps || (state.deps = {}); + let parent = identifier.parentPath; - if (isCoreTag("const", binding.path)) { - // Const tag reflects the default value as dependencies. - const nestedState: DepsVisitorState = state.shallow - ? state - : { root: state.root, shallow: true }; - getAttr(bindingTag, "value")!.traverse(depsVisitor, nestedState); - isDep = !!nestedState.deps; - } else { - isDep = true; - } + do { + const curDeps = deps[name]; + if (curDeps === true) return; - if (isDep) { - if (state.shallow) { - state.deps = true; - identifier.stop(); - } else { - ((state.deps || (state.deps = new Set())) as Set).add( - identifier.node.name - ); - } + if ( + parent.isMemberExpression() && + (!parent.node.computed || + isStringOrNumericLiteral(parent.node.property.type)) + ) { + const prop = parent.node.property as + | t.Identifier + | t.StringLiteral + | t.NumericLiteral; + parent = parent.parentPath; + deps = curDeps || (deps[name] = {} as Deps); + name = prop.type === "Identifier" ? prop.name : prop.value + ""; + } else { + deps[name] = true; + return; } - } + // eslint-disable-next-line no-constant-condition + } while (true); } }) as t.Visitor["Identifier"], } as t.Visitor; @@ -63,7 +72,7 @@ export default { return; } - const state: DepsVisitorState & { deps?: Set } = { root: fn }; + const state: DepsVisitorState = { rootFn: fn, parentTag }; fn.skip(); fn.traverse(depsVisitor, state); @@ -80,9 +89,7 @@ export default { importRuntimeNamed(file, "transform/cached-function", "cached"), [ component, - t.arrayExpression( - state.deps ? Array.from(state.deps, toIdentifier) : [] - ), + t.arrayExpression(state.deps ? toDepsArray(state.deps) : []), ] ), fn.node @@ -93,6 +100,33 @@ export default { }, } as t.Visitor; -function toIdentifier(val: string) { - return t.identifier(val); +function isStringOrNumericLiteral(type: string) { + switch (type) { + case "StringLiteral": + case "NumericLiteral": + return true; + default: + return false; + } +} + +function toDepsArray( + deps: Deps, + object?: t.Expression, + arr: (t.Identifier | t.MemberExpression)[] = [] +) { + for (const name in deps) { + const dep = deps[name]; + const node = object + ? t.memberExpression(object, t.stringLiteral(name), true) + : t.identifier(name); + + if (dep === true) { + arr.push(node); + } else { + toDepsArray(dep, node, arr); + } + } + + return arr; }