mirror of
https://github.com/marko-js/marko.git
synced 2026-02-01 16:07:13 +00:00
fix: support assigning to destructured tag variables
This commit is contained in:
parent
1721ef1f81
commit
79cfb0fbd1
5
.changeset/shy-sheep-juggle.md
Normal file
5
.changeset/shy-sheep-juggle.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@marko/runtime-tags": patch
|
||||
---
|
||||
|
||||
Fix support for assigning to tag variables from a destructure.
|
||||
@ -0,0 +1,12 @@
|
||||
{
|
||||
"vars": {
|
||||
"props": {
|
||||
"$_$": "t",
|
||||
"$init": "o",
|
||||
"$$bar_effect": "r",
|
||||
"$$bar": "n",
|
||||
"$$expr_bar_$fooChange_effect": "i",
|
||||
"$$expr_bar_$fooChange": "a"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
# Render
|
||||
```html
|
||||
<button>
|
||||
1:0
|
||||
</button>
|
||||
```
|
||||
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<button>
|
||||
1:1
|
||||
</button>
|
||||
```
|
||||
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<button>
|
||||
1:2
|
||||
</button>
|
||||
```
|
||||
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<button>
|
||||
1:3
|
||||
</button>
|
||||
```
|
||||
@ -0,0 +1,56 @@
|
||||
# Render
|
||||
```html
|
||||
<button>
|
||||
1:0
|
||||
</button>
|
||||
```
|
||||
|
||||
# Mutations
|
||||
```
|
||||
INSERT button
|
||||
```
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<button>
|
||||
1:1
|
||||
</button>
|
||||
```
|
||||
|
||||
# Mutations
|
||||
```
|
||||
UPDATE button/#text2 "0" => "1"
|
||||
```
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<button>
|
||||
1:2
|
||||
</button>
|
||||
```
|
||||
|
||||
# Mutations
|
||||
```
|
||||
UPDATE button/#text2 "1" => "2"
|
||||
```
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<button>
|
||||
1:3
|
||||
</button>
|
||||
```
|
||||
|
||||
# Mutations
|
||||
```
|
||||
UPDATE button/#text2 "2" => "3"
|
||||
```
|
||||
@ -0,0 +1,18 @@
|
||||
// size: 209 (min) 147 (brotli)
|
||||
const $expr_bar_$fooChange_effect = _$.effect(
|
||||
"a1",
|
||||
($scope, { 3: bar, 6: $fooChange }) =>
|
||||
_$.on($scope[0], "click", function () {
|
||||
$fooChange(bar + 1);
|
||||
}),
|
||||
),
|
||||
$expr_bar_$fooChange = _$.intersection(7, $expr_bar_$fooChange_effect),
|
||||
$bar = _$.state(3, ($scope, bar) => {
|
||||
_$.data($scope[2], bar), $expr_bar_$fooChange($scope);
|
||||
});
|
||||
_$.register("a0", function ($scope) {
|
||||
return function (v) {
|
||||
$bar($scope, v);
|
||||
};
|
||||
}),
|
||||
init();
|
||||
@ -0,0 +1,34 @@
|
||||
export const $template = "<button><!>:<!></button>";
|
||||
export const $walks = /* get, next(1), replace, over(2), replace, out(1) */" D%c%l";
|
||||
import * as _$ from "@marko/runtime-tags/debug/dom";
|
||||
const $expr_bar_$fooChange_effect = _$.effect("__tests__/template.marko_0_bar_$fooChange", ($scope, {
|
||||
bar,
|
||||
$fooChange
|
||||
}) => _$.on($scope["#button/0"], "click", function () {
|
||||
$fooChange(bar + 1);
|
||||
}));
|
||||
const $expr_bar_$fooChange = /* @__PURE__ */_$.intersection(7, $expr_bar_$fooChange_effect);
|
||||
const $bar = /* @__PURE__ */_$.state("bar/3", ($scope, bar) => {
|
||||
_$.data($scope["#text/2"], bar);
|
||||
$expr_bar_$fooChange($scope);
|
||||
});
|
||||
const $pattern2 = /* @__PURE__ */_$.value("$pattern", ($scope, $pattern) => {
|
||||
$foo2($scope, $pattern.foo);
|
||||
$fooChange2($scope, $pattern.fooChange);
|
||||
});
|
||||
export function $setup($scope) {
|
||||
$bar($scope, 0);
|
||||
$pattern2($scope, {
|
||||
foo: 1,
|
||||
fooChange: $foo($scope)
|
||||
});
|
||||
}
|
||||
const $foo2 = /* @__PURE__ */_$.value("foo", ($scope, foo) => _$.data($scope["#text/1"], foo));
|
||||
const $fooChange2 = /* @__PURE__ */_$.value("$fooChange", $expr_bar_$fooChange);
|
||||
function $foo($scope) {
|
||||
return function (v) {
|
||||
$bar($scope, v);
|
||||
};
|
||||
}
|
||||
_$.register("__tests__/template.marko_0/foo", $foo);
|
||||
export default /* @__PURE__ */_$.createTemplate("__tests__/template.marko", $template, $walks, $setup);
|
||||
@ -0,0 +1,24 @@
|
||||
import * as _$ from "@marko/runtime-tags/debug/html";
|
||||
export default _$.createTemplate("__tests__/template.marko", input => {
|
||||
const $scope0_id = _$.nextScopeId();
|
||||
let bar = 0;
|
||||
const {
|
||||
foo,
|
||||
fooChange: $fooChange
|
||||
} = {
|
||||
foo: 1,
|
||||
fooChange: _$.register(function (v) {
|
||||
bar = v;
|
||||
}, "__tests__/template.marko_0/foo", $scope0_id)
|
||||
};
|
||||
_$.write(`<button>${_$.escapeXML(foo)}:<!>${_$.escapeXML(bar)}${_$.markResumeNode($scope0_id, "#text/2")}</button>${_$.markResumeNode($scope0_id, "#button/0")}`);
|
||||
_$.writeEffect($scope0_id, "__tests__/template.marko_0_bar_$fooChange");
|
||||
_$.writeScope($scope0_id, {
|
||||
bar,
|
||||
$fooChange
|
||||
}, "__tests__/template.marko", 0, {
|
||||
bar: "1:5",
|
||||
$fooChange: "9:20"
|
||||
});
|
||||
_$.resumeClosestBranch($scope0_id);
|
||||
});
|
||||
@ -0,0 +1,39 @@
|
||||
# Render
|
||||
```html
|
||||
<button>
|
||||
1:0
|
||||
</button>
|
||||
```
|
||||
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<button>
|
||||
1:1
|
||||
</button>
|
||||
```
|
||||
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<button>
|
||||
1:2
|
||||
</button>
|
||||
```
|
||||
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<button>
|
||||
1:3
|
||||
</button>
|
||||
```
|
||||
@ -0,0 +1,100 @@
|
||||
# Render
|
||||
```html
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<button>
|
||||
1:
|
||||
<!---->
|
||||
0
|
||||
<!--M_*1 #text/2-->
|
||||
</button>
|
||||
<!--M_*1 #button/0-->
|
||||
<script>
|
||||
WALKER_RUNTIME("M")("_");M._.r=[_=>(_.b=[0,_.a={bar:0}],_.a.$fooChange=_._["__tests__/template.marko_0/foo"](_.a),_.b),"__tests__/template.marko_0_bar_$fooChange",1];M._.w()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<button>
|
||||
1:
|
||||
<!---->
|
||||
1
|
||||
<!--M_*1 #text/2-->
|
||||
</button>
|
||||
<!--M_*1 #button/0-->
|
||||
<script>
|
||||
WALKER_RUNTIME("M")("_");M._.r=[_=>(_.b=[0,_.a={bar:0}],_.a.$fooChange=_._["__tests__/template.marko_0/foo"](_.a),_.b),"__tests__/template.marko_0_bar_$fooChange",1];M._.w()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
# Mutations
|
||||
```
|
||||
UPDATE html/body/button/#text1 "0" => "1"
|
||||
```
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<button>
|
||||
1:
|
||||
<!---->
|
||||
2
|
||||
<!--M_*1 #text/2-->
|
||||
</button>
|
||||
<!--M_*1 #button/0-->
|
||||
<script>
|
||||
WALKER_RUNTIME("M")("_");M._.r=[_=>(_.b=[0,_.a={bar:0}],_.a.$fooChange=_._["__tests__/template.marko_0/foo"](_.a),_.b),"__tests__/template.marko_0_bar_$fooChange",1];M._.w()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
# Mutations
|
||||
```
|
||||
UPDATE html/body/button/#text1 "1" => "2"
|
||||
```
|
||||
|
||||
# Render
|
||||
```js
|
||||
container.querySelector("button").click();
|
||||
```
|
||||
```html
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<button>
|
||||
1:
|
||||
<!---->
|
||||
3
|
||||
<!--M_*1 #text/2-->
|
||||
</button>
|
||||
<!--M_*1 #button/0-->
|
||||
<script>
|
||||
WALKER_RUNTIME("M")("_");M._.r=[_=>(_.b=[0,_.a={bar:0}],_.a.$fooChange=_._["__tests__/template.marko_0/foo"](_.a),_.b),"__tests__/template.marko_0_bar_$fooChange",1];M._.w()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
# Mutations
|
||||
```
|
||||
UPDATE html/body/button/#text1 "2" => "3"
|
||||
```
|
||||
@ -0,0 +1,6 @@
|
||||
# Render End
|
||||
```html
|
||||
<button>
|
||||
1:0
|
||||
</button>
|
||||
```
|
||||
@ -0,0 +1,38 @@
|
||||
# Write
|
||||
```html
|
||||
<button>1:<!>0<!--M_*1 #text/2--></button><!--M_*1 #button/0--><script>WALKER_RUNTIME("M")("_");M._.r=[_=>(_.b=[0,_.a={bar:0}],_.a.$fooChange=_._["__tests__/template.marko_0/foo"](_.a),_.b),"__tests__/template.marko_0_bar_$fooChange",1];M._.w()</script>
|
||||
```
|
||||
|
||||
# Render End
|
||||
```html
|
||||
<html>
|
||||
<head />
|
||||
<body>
|
||||
<button>
|
||||
1:
|
||||
<!---->
|
||||
0
|
||||
<!--M_*1 #text/2-->
|
||||
</button>
|
||||
<!--M_*1 #button/0-->
|
||||
<script>
|
||||
WALKER_RUNTIME("M")("_");M._.r=[_=>(_.b=[0,_.a={bar:0}],_.a.$fooChange=_._["__tests__/template.marko_0/foo"](_.a),_.b),"__tests__/template.marko_0_bar_$fooChange",1];M._.w()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
# Mutations
|
||||
```
|
||||
INSERT html
|
||||
INSERT html/head
|
||||
INSERT html/body
|
||||
INSERT html/body/button
|
||||
INSERT html/body/button/#text0
|
||||
INSERT html/body/button/#comment0
|
||||
INSERT html/body/button/#text1
|
||||
INSERT html/body/button/#comment1
|
||||
INSERT html/body/#comment
|
||||
INSERT html/body/script
|
||||
INSERT html/body/script/#text
|
||||
```
|
||||
@ -0,0 +1,10 @@
|
||||
let/bar=0
|
||||
const/{ foo }={
|
||||
foo: 1,
|
||||
fooChange(v) {
|
||||
bar = v;
|
||||
}
|
||||
}
|
||||
|
||||
button onClick() { foo = bar + 1 }
|
||||
-- ${foo}:${bar}
|
||||
@ -0,0 +1,5 @@
|
||||
export const steps = [{}, click, click, click];
|
||||
|
||||
function click(container: Element) {
|
||||
container.querySelector("button")!.click();
|
||||
}
|
||||
@ -42,3 +42,37 @@ export function forEachIdentifier(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function forEachIdentifierPath(
|
||||
nodePath: t.NodePath<any>,
|
||||
cb: (identifier: t.NodePath<t.Identifier>) => void,
|
||||
) {
|
||||
if (nodePath.isIdentifier()) {
|
||||
cb(nodePath);
|
||||
} else if (nodePath.isObjectPattern()) {
|
||||
for (const prop of nodePath.get("properties")) {
|
||||
if (prop.isObjectProperty()) {
|
||||
const value = prop.get("value");
|
||||
if (value.isAssignmentPattern()) {
|
||||
forEachIdentifierPath(value.get("left"), cb);
|
||||
} else {
|
||||
forEachIdentifierPath(value, cb);
|
||||
}
|
||||
} else if (prop.isRestElement()) {
|
||||
forEachIdentifierPath(prop.get("argument"), cb);
|
||||
}
|
||||
}
|
||||
} else if (nodePath.isArrayPattern()) {
|
||||
for (const el of nodePath.get("elements")) {
|
||||
if (el) {
|
||||
if (el.isRestElement()) {
|
||||
forEachIdentifierPath(el.get("argument"), cb);
|
||||
} else if (el.isAssignmentPattern()) {
|
||||
forEachIdentifierPath(el.get("left"), cb);
|
||||
} else {
|
||||
forEachIdentifierPath(el, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import { getProgram } from "@marko/compiler/babel-utils";
|
||||
|
||||
import { toAccess } from "../../html/serializer";
|
||||
import type { InputSerializeReasons } from "../visitors/program";
|
||||
import { forEachIdentifier } from "./for-each-identifier";
|
||||
import { forEachIdentifierPath } from "./for-each-identifier";
|
||||
import { generateUid } from "./generate-uid";
|
||||
import { getAccessorPrefix, getAccessorProp } from "./get-accessor-char";
|
||||
import { getExprRoot, getFnRoot } from "./get-root";
|
||||
@ -121,6 +121,7 @@ declare module "@marko/compiler/dist/types" {
|
||||
referencedBindings?: ReferencedBindings;
|
||||
binding?: Binding;
|
||||
assignment?: Binding;
|
||||
assignmentTo?: Binding;
|
||||
read?: { binding: Binding; props: Opt<string> };
|
||||
pruned?: true;
|
||||
isEffect?: true;
|
||||
@ -359,9 +360,27 @@ function trackAssignment(
|
||||
) {
|
||||
const section = getOrCreateSection(assignment);
|
||||
setReferencesScope(assignment);
|
||||
forEachIdentifier(assignment.node, (id) => {
|
||||
if (id.name === binding.name) {
|
||||
const extra = (id.extra ??= {});
|
||||
forEachIdentifierPath(assignment, (id) => {
|
||||
if (id.node.name === binding.name) {
|
||||
const extra = (id.node.extra ??= {});
|
||||
|
||||
if (binding.upstreamAlias && binding.property !== undefined) {
|
||||
const changePropName = binding.property + "Change";
|
||||
const changeBinding =
|
||||
binding.upstreamAlias.propertyAliases.get(changePropName) ||
|
||||
createBinding(
|
||||
generateUid(changePropName),
|
||||
BindingType.derived,
|
||||
binding.section,
|
||||
binding.upstreamAlias,
|
||||
changePropName,
|
||||
id.node.loc,
|
||||
true,
|
||||
);
|
||||
extra.assignmentTo = changeBinding;
|
||||
addReadToExpression(id, changeBinding);
|
||||
}
|
||||
|
||||
binding.assignmentSections = sectionUtil.add(
|
||||
binding.assignmentSections,
|
||||
section,
|
||||
@ -547,22 +566,7 @@ function trackReference(
|
||||
);
|
||||
}
|
||||
|
||||
const fnRoot = getFnRoot(root);
|
||||
const exprRoot = getExprRoot(fnRoot || root);
|
||||
const { section } = addReadToExpression(exprRoot, reference, root.node);
|
||||
|
||||
if (fnRoot) {
|
||||
const readsByFn = getReadsByFunction();
|
||||
const fnExtra = (fnRoot.node.extra ??= {}) as FnExtra;
|
||||
fnExtra.section = section;
|
||||
readsByFn.set(
|
||||
fnExtra,
|
||||
push(readsByFn.get(fnExtra), {
|
||||
binding: reference,
|
||||
node: root.node,
|
||||
}),
|
||||
);
|
||||
}
|
||||
addReadToExpression(root, reference);
|
||||
}
|
||||
|
||||
const [getMergedReferences] = createProgramState(
|
||||
@ -1162,19 +1166,28 @@ const [getReadsByFunction] = createProgramState(
|
||||
() => new Map<FnExtra, Opt<Read>>(),
|
||||
);
|
||||
|
||||
export function addReadToExpression(
|
||||
path: t.NodePath,
|
||||
function addReadToExpression(
|
||||
root: t.NodePath<t.Identifier> | t.NodePath<t.MemberExpression>,
|
||||
binding: Binding,
|
||||
node?: t.Identifier | t.MemberExpression,
|
||||
) {
|
||||
const exprExtra = (path.node.extra ??= {}) as ReferencedExtra;
|
||||
const { node } = root;
|
||||
const fnRoot = getFnRoot(root);
|
||||
const exprRoot = getExprRoot(fnRoot || root);
|
||||
const exprExtra = (exprRoot.node.extra ??= {}) as ReferencedExtra;
|
||||
const readsByExpression = getReadsByExpression();
|
||||
exprExtra.section = getOrCreateSection(path);
|
||||
const section = (exprExtra.section = getOrCreateSection(exprRoot));
|
||||
const read: Read = { binding, node };
|
||||
readsByExpression.set(
|
||||
exprExtra,
|
||||
push(readsByExpression.get(exprExtra), { binding, node }),
|
||||
push(readsByExpression.get(exprExtra), read),
|
||||
);
|
||||
return exprExtra;
|
||||
|
||||
if (fnRoot) {
|
||||
const readsByFn = getReadsByFunction();
|
||||
const fnExtra = (fnRoot.node.extra ??= {}) as FnExtra;
|
||||
fnExtra.section = section;
|
||||
readsByFn.set(fnExtra, push(readsByFn.get(fnExtra), read));
|
||||
}
|
||||
}
|
||||
|
||||
export function dropReferences(node: t.Node | t.Node[]) {
|
||||
|
||||
@ -19,6 +19,7 @@ import { getDeclaredBindingExpression } from "./get-defined-binding-expression";
|
||||
import { isOptimize, isOutputHTML } from "./marko-config";
|
||||
import { find, forEach, type Opt, push } from "./optional";
|
||||
import {
|
||||
type AssignedBindingExtra,
|
||||
type Binding,
|
||||
BindingType,
|
||||
bindingUtil,
|
||||
@ -1283,10 +1284,7 @@ function replaceAssignedNode(node: t.Node) {
|
||||
case "UpdateExpression": {
|
||||
const { extra } = node.argument;
|
||||
if (isAssignedBindingExtra(extra)) {
|
||||
const { buildAssignment } = getSignal(
|
||||
extra.assignment.section,
|
||||
extra.assignment,
|
||||
);
|
||||
const buildAssignment = getBuildAssignment(extra);
|
||||
if (buildAssignment) {
|
||||
const replacement = buildAssignment(
|
||||
extra.section,
|
||||
@ -1310,10 +1308,7 @@ function replaceAssignedNode(node: t.Node) {
|
||||
case "Identifier": {
|
||||
const { extra } = node.left;
|
||||
if (isAssignedBindingExtra(extra)) {
|
||||
const { buildAssignment } = getSignal(
|
||||
extra.assignment.section,
|
||||
extra.assignment,
|
||||
);
|
||||
const buildAssignment = getBuildAssignment(extra);
|
||||
if (buildAssignment) {
|
||||
return buildAssignment(
|
||||
extra.section,
|
||||
@ -1339,15 +1334,12 @@ function replaceAssignedNode(node: t.Node) {
|
||||
forEachIdentifier(node.left, (id) => {
|
||||
const { extra } = id;
|
||||
if (isAssignedBindingExtra(extra)) {
|
||||
const signal = getSignal(
|
||||
extra.assignment.section,
|
||||
extra.assignment,
|
||||
);
|
||||
if (signal?.buildAssignment) {
|
||||
const buildAssignment = getBuildAssignment(extra);
|
||||
if (buildAssignment) {
|
||||
id.name = generateUid(id.name);
|
||||
(params ||= []).push(t.identifier(id.name));
|
||||
(assignments ||= []).push(
|
||||
signal.buildAssignment(extra.section, t.identifier(id.name)),
|
||||
buildAssignment(extra.section, t.identifier(id.name)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1377,6 +1369,17 @@ function replaceAssignedNode(node: t.Node) {
|
||||
}
|
||||
}
|
||||
|
||||
function getBuildAssignment(extra: AssignedBindingExtra) {
|
||||
const { assignmentTo, assignment } = extra;
|
||||
if (assignmentTo) {
|
||||
return (_section: Section, value: t.Expression) => {
|
||||
return t.callExpression(t.identifier(assignmentTo.name), [value]);
|
||||
};
|
||||
}
|
||||
|
||||
return getSignal(assignment.section, assignment).buildAssignment;
|
||||
}
|
||||
|
||||
const registeredFnsForProgram = new WeakMap<
|
||||
t.Program,
|
||||
{
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { types as t } from "@marko/compiler";
|
||||
|
||||
import { forEachIdentifierPath } from "./for-each-identifier";
|
||||
|
||||
export default function translateVar(
|
||||
tag: t.NodePath<t.MarkoTag>,
|
||||
initialValue: t.Expression,
|
||||
@ -13,7 +15,44 @@ export default function translateVar(
|
||||
return;
|
||||
}
|
||||
|
||||
forEachIdentifierPath(tag.get("var"), (id) => {
|
||||
const binding = id.node.extra?.binding;
|
||||
if (
|
||||
!binding ||
|
||||
!binding.upstreamAlias ||
|
||||
!binding.assignmentSections ||
|
||||
id.node === tagVar
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const changeName = binding.name + "Change";
|
||||
const changeBinding = binding.upstreamAlias.propertyAliases.get(changeName);
|
||||
if (changeBinding && changeName !== changeBinding.name) {
|
||||
// add a new property to the destructure list when a change handler is implicitly added
|
||||
// eg by assigning to a destructured property.
|
||||
getDestructurePattern(id)?.pushContainer(
|
||||
"properties",
|
||||
t.objectProperty(
|
||||
t.identifier(changeName),
|
||||
t.identifier(changeBinding.name),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
tag.insertBefore(
|
||||
t.variableDeclaration(kind, [t.variableDeclarator(tagVar, initialValue)]),
|
||||
);
|
||||
}
|
||||
|
||||
function getDestructurePattern(id: t.NodePath<t.Identifier>) {
|
||||
let cur: t.NodePath | null = id;
|
||||
|
||||
while (cur) {
|
||||
if (cur.node.type === "ObjectPattern") {
|
||||
return cur as t.NodePath<t.ObjectPattern>;
|
||||
}
|
||||
cur = cur.parentPath;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user