diff --git a/.changeset/wet-lizards-repair.md b/.changeset/wet-lizards-repair.md new file mode 100644 index 000000000..a7d3a5f1d --- /dev/null +++ b/.changeset/wet-lizards-repair.md @@ -0,0 +1,5 @@ +--- +"marko": patch +--- + +Fix issue where scoped directive was being applied twice when tag had no-update directive. diff --git a/packages/runtime-class/src/translator/tag/attribute/modifiers/scoped.js b/packages/runtime-class/src/translator/tag/attribute/modifiers/scoped.js index 09b08354d..d55c725e5 100644 --- a/packages/runtime-class/src/translator/tag/attribute/modifiers/scoped.js +++ b/packages/runtime-class/src/translator/tag/attribute/modifiers/scoped.js @@ -2,22 +2,27 @@ import { types as t } from "@marko/compiler"; import withPreviousLocation from "../../../util/with-previous-location"; +const seen = new WeakSet(); + export default { exit(tag, _, value) { const { hub: { file }, } = tag; - value.replaceWith( - withPreviousLocation( - t.callExpression( - t.memberExpression( - file._componentDefIdentifier, - t.identifier("elId"), - ), - [value.node], - ), - value.node, + + if (seen.has(value.node)) { + return; + } + + const replacement = withPreviousLocation( + t.callExpression( + t.memberExpression(file._componentDefIdentifier, t.identifier("elId")), + [value.node], ), + value.node, ); + + seen.add(replacement); + value.replaceWith(replacement); }, }; diff --git a/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/cjs-expected.js b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/cjs-expected.js new file mode 100644 index 000000000..6bf7fa5f1 --- /dev/null +++ b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/cjs-expected.js @@ -0,0 +1,27 @@ +"use strict"; + +exports.__esModule = true; +exports.default = void 0; +var _index = require("marko/src/runtime/html/index.js"); +var _dataMarko = _interopRequireDefault(require("marko/src/runtime/html/helpers/data-marko.js")); +var _attr = _interopRequireDefault(require("marko/src/runtime/html/helpers/attr.js")); +var _preserveTag = _interopRequireDefault(require("marko/src/core-tags/components/preserve-tag.js")); +var _renderTag = _interopRequireDefault(require("marko/src/runtime/helpers/render-tag.js")); +var _renderer = _interopRequireDefault(require("marko/src/runtime/components/renderer.js")); +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +const _marko_componentType = "__tests__/template.marko", + _marko_template = (0, _index.t)(_marko_componentType); +var _default = exports.default = _marko_template; +const _marko_component = {}; +_marko_template._ = (0, _renderer.default)(function (input, out, _componentDef, _component, state, $global) { + (0, _renderTag.default)(_preserveTag.default, { + "n": true, + "renderBody": out => { + out.w(``); + } + }, out, _componentDef, "0"); +}, { + t: _marko_componentType, + i: true, + d: true +}, _marko_component); \ No newline at end of file diff --git a/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/generated-expected.marko b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/generated-expected.marko new file mode 100644 index 000000000..b6e405569 --- /dev/null +++ b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/generated-expected.marko @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/html-expected.js b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/html-expected.js new file mode 100644 index 000000000..4b2ff77c1 --- /dev/null +++ b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/html-expected.js @@ -0,0 +1,22 @@ +import { t as _t } from "marko/src/runtime/html/index.js"; +const _marko_componentType = "__tests__/template.marko", + _marko_template = _t(_marko_componentType); +export default _marko_template; +import _marko_props from "marko/src/runtime/html/helpers/data-marko.js"; +import _marko_attr from "marko/src/runtime/html/helpers/attr.js"; +import _preserve from "marko/src/core-tags/components/preserve-tag.js"; +import _marko_tag from "marko/src/runtime/helpers/render-tag.js"; +import _marko_renderer from "marko/src/runtime/components/renderer.js"; +const _marko_component = {}; +_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) { + _marko_tag(_preserve, { + "n": true, + "renderBody": out => { + out.w(``); + } + }, out, _componentDef, "0"); +}, { + t: _marko_componentType, + i: true, + d: true +}, _marko_component); \ No newline at end of file diff --git a/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/htmlProduction-expected.js b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/htmlProduction-expected.js new file mode 100644 index 000000000..8959b0a0c --- /dev/null +++ b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/htmlProduction-expected.js @@ -0,0 +1,21 @@ +import { t as _t } from "marko/dist/runtime/html/index.js"; +const _marko_componentType = "FiW8Sbt", + _marko_template = _t(_marko_componentType); +export default _marko_template; +import _marko_props from "marko/dist/runtime/html/helpers/data-marko.js"; +import _marko_attr from "marko/dist/runtime/html/helpers/attr.js"; +import _preserve from "marko/dist/core-tags/components/preserve-tag.js"; +import _marko_tag from "marko/dist/runtime/helpers/render-tag.js"; +import _marko_renderer from "marko/dist/runtime/components/renderer.js"; +const _marko_component = {}; +_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) { + _marko_tag(_preserve, { + "n": true, + "renderBody": out => { + out.w(``); + } + }, out, _componentDef, "0"); +}, { + t: _marko_componentType, + i: true +}, _marko_component); \ No newline at end of file diff --git a/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/hydrate-expected.js b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/hydrate-expected.js new file mode 100644 index 000000000..e69de29bb diff --git a/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/vdom-expected.js b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/vdom-expected.js new file mode 100644 index 000000000..d1d8232e3 --- /dev/null +++ b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/vdom-expected.js @@ -0,0 +1,26 @@ +import { t as _t } from "marko/src/runtime/vdom/index.js"; +const _marko_componentType = "__tests__/template.marko", + _marko_template = _t(_marko_componentType); +export default _marko_template; +import _preserve from "marko/src/core-tags/components/preserve-tag.js"; +import _marko_tag from "marko/src/runtime/helpers/render-tag.js"; +import _marko_renderer from "marko/src/runtime/components/renderer.js"; +import { r as _marko_registerComponent } from "marko/src/runtime/components/registry.js"; +_marko_registerComponent(_marko_componentType, () => _marko_template); +const _marko_component = {}; +_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) { + _marko_tag(_preserve, { + "n": true, + "renderBody": out => { + out.e("input", { + "id": _componentDef.elId("input1") + }, "0", _component, 0, 1); + } + }, out, _componentDef, "0"); +}, { + t: _marko_componentType, + i: true, + d: true +}, _marko_component); +import _marko_defineComponent from "marko/src/runtime/components/defineComponent.js"; +_marko_template.Component = _marko_defineComponent(_marko_component, _marko_template._); \ No newline at end of file diff --git a/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/vdomProduction-expected.js b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/vdomProduction-expected.js new file mode 100644 index 000000000..bd5e9b516 --- /dev/null +++ b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/snapshots/vdomProduction-expected.js @@ -0,0 +1,25 @@ +import { t as _t } from "marko/dist/runtime/vdom/index.js"; +const _marko_componentType = "FiW8Sbt", + _marko_template = _t(_marko_componentType); +export default _marko_template; +import _preserve from "marko/dist/core-tags/components/preserve-tag.js"; +import _marko_tag from "marko/dist/runtime/helpers/render-tag.js"; +import _marko_renderer from "marko/dist/runtime/components/renderer.js"; +import { r as _marko_registerComponent } from "marko/dist/runtime/components/registry.js"; +_marko_registerComponent(_marko_componentType, () => _marko_template); +const _marko_component = {}; +_marko_template._ = _marko_renderer(function (input, out, _componentDef, _component, state, $global) { + _marko_tag(_preserve, { + "n": true, + "renderBody": out => { + out.e("input", { + "id": _componentDef.elId("input1") + }, "0", _component, 0, 1); + } + }, out, _componentDef, "0"); +}, { + t: _marko_componentType, + i: true +}, _marko_component); +import _marko_defineComponent from "marko/dist/runtime/components/defineComponent.js"; +_marko_template.Component = _marko_defineComponent(_marko_component, _marko_template._); \ No newline at end of file diff --git a/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/template.marko b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/template.marko new file mode 100644 index 000000000..415bba2bc --- /dev/null +++ b/packages/runtime-class/test/translator/fixtures/attr-no-update-scoped/template.marko @@ -0,0 +1 @@ +