marko 5.39.8 → 5.39.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,7 @@ exports.p = function (htmlCompat) {
17
17
  const writeClassAPIResultToTagsAPI = ({ out }) => {
18
18
  const { writer } = out._state;
19
19
  htmlCompat.write(writer._content);
20
- htmlCompat.writeScript(writer._script);
20
+ htmlCompat.writeScript(writer._scripts);
21
21
  writer._content = writer._scripts = "";
22
22
 
23
23
  if (out.b_) {
@@ -14,6 +14,7 @@ var _babelUtils = require("@marko/compiler/babel-utils");
14
14
 
15
15
 
16
16
 
17
+
17
18
  var _package = require("marko/package.json");exports.version = _package.version;
18
19
  var _path = require("path");
19
20
 
@@ -148,6 +149,39 @@ const analyze = exports.analyze = {
148
149
  tag.node.extra.featureType = "tags";
149
150
  (file.path.node.extra ??= {}).needsCompat = true;
150
151
  }
152
+ } else if ((0, _babelUtils.isDynamicTag)(tag)) {
153
+ // A dynamic `<${expr}/>` whose name references an imported Tags API
154
+ // template crosses the interop boundary and must be rendered through the
155
+ // compat dynamic tag, the same as a statically named tags import. This
156
+ // mirrors the Tags API translator, which resolves the whole name
157
+ // expression (identifiers, conditionals, etc.) to detect the boundary.
158
+ const markIfTagsImport = (scope, name) => {
159
+ const binding = name && scope.getBinding(name);
160
+ if (binding && binding.kind === "module" && binding.identifier.loc) {
161
+ const childFile = (0, _babelUtils.loadFileForImport)(
162
+ file,
163
+ binding.path.parent.source.value
164
+ );
165
+ if (childFile?.ast.program.extra?.featureType === "tags") {
166
+ (tag.node.extra ??= {}).featureType = "tags";
167
+ (file.path.node.extra ??= {}).needsCompat = true;
168
+ return true;
169
+ }
170
+ }
171
+ };
172
+
173
+ const namePath = tag.get("name");
174
+ if (namePath.isIdentifier()) {
175
+ markIfTagsImport(namePath.scope, namePath.node.name);
176
+ } else {
177
+ namePath.traverse({
178
+ ReferencedIdentifier(idPath) {
179
+ if (markIfTagsImport(idPath.scope, idPath.node.name)) {
180
+ idPath.stop();
181
+ }
182
+ }
183
+ });
184
+ }
151
185
  }
152
186
 
153
187
  if (!(meta.hasFunctionEventHandlers || meta.hasStringEventHandlers)) {
@@ -26,12 +26,16 @@ function _default(path, isNullable) {
26
26
  let tagIdentifier;
27
27
 
28
28
  if (node.extra?.featureType === "tags") {
29
- path.set(
30
- "name",
31
- path.scope.hasBinding(name.value) ?
32
- _compiler.types.identifier(name.value) :
33
- (0, _babelUtils.importDefault)(file, node.extra.relativePath, name.value)
34
- );
29
+ // A dynamic `<${tagName}>` already references the imported template
30
+ // binding directly; only a static tag name needs to be resolved to one.
31
+ if (_compiler.types.isStringLiteral(name)) {
32
+ path.set(
33
+ "name",
34
+ path.scope.hasBinding(name.value) ?
35
+ _compiler.types.identifier(name.value) :
36
+ (0, _babelUtils.importDefault)(file, node.extra.relativePath, name.value)
37
+ );
38
+ }
35
39
  return (0, _dynamicTag.default)(path);
36
40
  }
37
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marko",
3
- "version": "5.39.8",
3
+ "version": "5.39.10",
4
4
  "private": false,
5
5
  "description": "UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.",
6
6
  "keywords": [
@@ -71,7 +71,7 @@
71
71
  },
72
72
  "dependencies": {
73
73
  "@marko/compiler": "^5.39.64",
74
- "@marko/runtime-tags": "^6.1.9",
74
+ "@marko/runtime-tags": "^6.1.16",
75
75
  "app-module-path": "^2.2.0",
76
76
  "argly": "^1.2.0",
77
77
  "browser-refresh-client": "1.1.4",
@@ -17,7 +17,7 @@ exports.p = function (htmlCompat) {
17
17
  const writeClassAPIResultToTagsAPI = ({ out }) => {
18
18
  const { writer } = out._state;
19
19
  htmlCompat.write(writer._content);
20
- htmlCompat.writeScript(writer._script);
20
+ htmlCompat.writeScript(writer._scripts);
21
21
  writer._content = writer._scripts = "";
22
22
 
23
23
  if (out.___components) {
@@ -8,6 +8,7 @@ import {
8
8
  isDynamicTag,
9
9
  isMacroTag,
10
10
  isNativeTag,
11
+ loadFileForImport,
11
12
  loadFileForTag,
12
13
  parseExpression,
13
14
  parseStatements,
@@ -148,6 +149,39 @@ export const analyze = {
148
149
  tag.node.extra.featureType = "tags";
149
150
  (file.path.node.extra ??= {}).needsCompat = true;
150
151
  }
152
+ } else if (isDynamicTag(tag)) {
153
+ // A dynamic `<${expr}/>` whose name references an imported Tags API
154
+ // template crosses the interop boundary and must be rendered through the
155
+ // compat dynamic tag, the same as a statically named tags import. This
156
+ // mirrors the Tags API translator, which resolves the whole name
157
+ // expression (identifiers, conditionals, etc.) to detect the boundary.
158
+ const markIfTagsImport = (scope, name) => {
159
+ const binding = name && scope.getBinding(name);
160
+ if (binding && binding.kind === "module" && binding.identifier.loc) {
161
+ const childFile = loadFileForImport(
162
+ file,
163
+ binding.path.parent.source.value,
164
+ );
165
+ if (childFile?.ast.program.extra?.featureType === "tags") {
166
+ (tag.node.extra ??= {}).featureType = "tags";
167
+ (file.path.node.extra ??= {}).needsCompat = true;
168
+ return true;
169
+ }
170
+ }
171
+ };
172
+
173
+ const namePath = tag.get("name");
174
+ if (namePath.isIdentifier()) {
175
+ markIfTagsImport(namePath.scope, namePath.node.name);
176
+ } else {
177
+ namePath.traverse({
178
+ ReferencedIdentifier(idPath) {
179
+ if (markIfTagsImport(idPath.scope, idPath.node.name)) {
180
+ idPath.stop();
181
+ }
182
+ },
183
+ });
184
+ }
151
185
  }
152
186
 
153
187
  if (!(meta.hasFunctionEventHandlers || meta.hasStringEventHandlers)) {
@@ -26,12 +26,16 @@ export default function (path, isNullable) {
26
26
  let tagIdentifier;
27
27
 
28
28
  if (node.extra?.featureType === "tags") {
29
- path.set(
30
- "name",
31
- path.scope.hasBinding(name.value)
32
- ? t.identifier(name.value)
33
- : importDefault(file, node.extra.relativePath, name.value),
34
- );
29
+ // A dynamic `<${tagName}>` already references the imported template
30
+ // binding directly; only a static tag name needs to be resolved to one.
31
+ if (t.isStringLiteral(name)) {
32
+ path.set(
33
+ "name",
34
+ path.scope.hasBinding(name.value)
35
+ ? t.identifier(name.value)
36
+ : importDefault(file, node.extra.relativePath, name.value),
37
+ );
38
+ }
35
39
  return dynamicTag(path);
36
40
  }
37
41