marko 6.0.94 → 6.0.96

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.
@@ -4207,7 +4207,7 @@ function replaceAssignedNode(node) {
4207
4207
  return getBuildAssignment(extra)?.(
4208
4208
  extra.section,
4209
4209
  bindingUtil.has(
4210
- extra.fnExtra?.referencedBindingsInFunction,
4210
+ extra.assignmentFunction.referencedBindingsInFunction,
4211
4211
  extra.assignment
4212
4212
  ) ? node : node.operator === "=" ? node.right : import_compiler22.types.binaryExpression(
4213
4213
  node.operator.slice(
@@ -4237,7 +4237,7 @@ function replaceAssignedNode(node) {
4237
4237
  );
4238
4238
  if (builtAssignment) {
4239
4239
  if (!bindingUtil.has(
4240
- extra.fnExtra?.referencedBindingsInFunction,
4240
+ extra.assignmentFunction.referencedBindingsInFunction,
4241
4241
  extra.assignment
4242
4242
  )) {
4243
4243
  id.name = uid;
@@ -7967,7 +7967,12 @@ function trackReferencesForBinding(babelBinding, binding) {
7967
7967
  const { referencePaths, constantViolations } = babelBinding;
7968
7968
  for (const ref of referencePaths) {
7969
7969
  const refSection = getOrCreateSection(ref);
7970
- if (isReferenceHoisted(babelBinding.path, ref)) {
7970
+ const markoRoot = getMarkoRoot(ref);
7971
+ if (markoRoot?.type === "MarkoAttribute" && markoRoot.parentPath === babelBinding.path) {
7972
+ throw ref.buildCodeFrameError(
7973
+ `Tag variable circular references are not supported.`
7974
+ );
7975
+ } else if (isReferenceHoisted(babelBinding.path, ref)) {
7971
7976
  trackHoistedReference(ref, binding);
7972
7977
  } else if (binding.type !== 4 /* local */ || refSection !== binding.section) {
7973
7978
  trackReference(ref, binding);
@@ -7992,12 +7997,24 @@ function trackReferencesForBinding(babelBinding, binding) {
7992
7997
  }
7993
7998
  function trackAssignment(assignment, binding) {
7994
7999
  const fnRoot = getFnRoot(assignment);
7995
- const fnExtra = fnRoot && (fnRoot.node.extra ??= {});
7996
8000
  const section = getOrCreateSection(assignment);
7997
8001
  setReferencesScope(assignment);
7998
8002
  forEachIdentifierPath(assignment, (id) => {
7999
8003
  if (id.node.name === binding.name) {
8000
- const extra = id.node.extra ??= {};
8004
+ if (!fnRoot) {
8005
+ throw id.buildCodeFrameError(
8006
+ `Assignments to a tag ${binding.type === 3 /* param */ ? "parameter" : "variable"} must be within a script or function.`
8007
+ );
8008
+ }
8009
+ const fnExtra = fnRoot && (fnRoot.node.extra ??= {});
8010
+ const idExtra = id.node.extra ??= {};
8011
+ idExtra.assignment = binding;
8012
+ idExtra.assignmentFunction = fnExtra;
8013
+ fnExtra.section = idExtra.section = section;
8014
+ binding.assignmentSections = sectionUtil.add(
8015
+ binding.assignmentSections,
8016
+ section
8017
+ );
8001
8018
  if (binding.upstreamAlias && binding.property !== void 0) {
8002
8019
  const changePropName = binding.property + "Change";
8003
8020
  const changeBinding = binding.upstreamAlias.propertyAliases.get(changePropName) || createBinding(
@@ -8010,16 +8027,9 @@ function trackAssignment(assignment, binding) {
8010
8027
  id.node.loc,
8011
8028
  true
8012
8029
  );
8013
- extra.assignmentTo = changeBinding;
8030
+ idExtra.assignmentTo = changeBinding;
8014
8031
  addReadToExpression(id, changeBinding);
8015
8032
  }
8016
- binding.assignmentSections = sectionUtil.add(
8017
- binding.assignmentSections,
8018
- section
8019
- );
8020
- extra.assignment = binding;
8021
- extra.section = section;
8022
- extra.fnExtra = fnExtra;
8023
8033
  }
8024
8034
  });
8025
8035
  }
@@ -8199,12 +8209,13 @@ function compareIntersections(a, b) {
8199
8209
  function finalizeReferences() {
8200
8210
  const bindings = getBindings();
8201
8211
  const readsByExpression = getReadsByExpression();
8202
- const readsByFn = getReadsByFunction();
8212
+ const fnReadsByExpression = getFunctionReadsByExpression();
8203
8213
  const mergedReferences = getMergedReferences();
8204
8214
  if (mergedReferences.size) {
8205
8215
  for (const [target, nodes] of mergedReferences) {
8206
8216
  const targetExtra = target.extra;
8207
8217
  let reads = readsByExpression.get(targetExtra);
8218
+ let exprFnReads = fnReadsByExpression.get(targetExtra);
8208
8219
  let { isEffect } = targetExtra;
8209
8220
  for (const node of nodes) {
8210
8221
  const extra = node?.extra;
@@ -8212,11 +8223,24 @@ function finalizeReferences() {
8212
8223
  setCanonicalExtra(extra, targetExtra);
8213
8224
  if (isReferencedExtra(extra)) {
8214
8225
  const additionalReads = readsByExpression.get(extra);
8226
+ const additionalExprFnReads = fnReadsByExpression.get(extra);
8215
8227
  isEffect ||= extra.isEffect;
8216
8228
  if (additionalReads) {
8217
8229
  reads = concat(reads, additionalReads);
8218
8230
  readsByExpression.delete(extra);
8219
8231
  }
8232
+ if (additionalExprFnReads) {
8233
+ if (exprFnReads) {
8234
+ for (const [key, value] of additionalExprFnReads) {
8235
+ exprFnReads.set(key, value);
8236
+ }
8237
+ } else {
8238
+ fnReadsByExpression.set(
8239
+ targetExtra,
8240
+ exprFnReads = new Map(additionalExprFnReads)
8241
+ );
8242
+ }
8243
+ }
8220
8244
  }
8221
8245
  }
8222
8246
  }
@@ -8227,14 +8251,25 @@ function finalizeReferences() {
8227
8251
  const intersectionsBySection = /* @__PURE__ */ new Map();
8228
8252
  for (const [expr, reads] of readsByExpression) {
8229
8253
  if (isReferencedExtra(expr)) {
8230
- expr.referencedBindings = resolveReferencedBindings(
8231
- expr,
8232
- reads,
8233
- intersectionsBySection
8234
- );
8235
- forEach(expr.referencedBindings, (binding) => {
8236
- binding.downstreamExpressions.add(expr);
8237
- });
8254
+ const referencedBindings = expr.referencedBindings = resolveReferencedBindings(expr, reads, intersectionsBySection);
8255
+ if (referencedBindings) {
8256
+ forEach(referencedBindings, (binding) => {
8257
+ binding.downstreamExpressions.add(expr);
8258
+ });
8259
+ const exprFnReads = fnReadsByExpression.get(expr);
8260
+ if (exprFnReads) {
8261
+ for (const [fn, fnReads] of exprFnReads) {
8262
+ if (fn === expr) {
8263
+ expr.referencedBindingsInFunction = referencedBindings;
8264
+ } else {
8265
+ fn.referencedBindingsInFunction = resolveReferencedBindingsInFunction(
8266
+ referencedBindings,
8267
+ fnReads
8268
+ );
8269
+ }
8270
+ }
8271
+ }
8272
+ }
8238
8273
  }
8239
8274
  }
8240
8275
  for (const binding of bindings) {
@@ -8404,20 +8439,29 @@ function finalizeReferences() {
8404
8439
  });
8405
8440
  });
8406
8441
  finalizeFunctionRegistry();
8407
- for (const [fn, reads] of readsByFn) {
8408
- const { registerReason } = fn;
8409
- fn.referencedBindingsInFunction = resolveReferencedBindings(
8410
- fn,
8411
- reads,
8412
- intersectionsBySection
8413
- );
8414
- if (registerReason) {
8415
- forEach(fn.referencedBindingsInFunction, (binding) => {
8416
- addSerializeReason(binding.section, registerReason, binding);
8417
- if (binding.section !== fn.section) {
8418
- addOwnerSerializeReason(fn.section, binding.section, registerReason);
8442
+ const referencedExprs = /* @__PURE__ */ new Set();
8443
+ for (const binding of bindings) {
8444
+ for (const expr of binding.downstreamExpressions) {
8445
+ referencedExprs.add(expr);
8446
+ }
8447
+ }
8448
+ for (const expr of referencedExprs) {
8449
+ const exprFnReads = fnReadsByExpression.get(expr);
8450
+ if (exprFnReads) {
8451
+ for (const fn of exprFnReads.keys()) {
8452
+ if (fn.registerReason) {
8453
+ forEach(fn.referencedBindingsInFunction, (binding) => {
8454
+ addSerializeReason(binding.section, fn.registerReason, binding);
8455
+ if (binding.section !== fn.section) {
8456
+ addOwnerSerializeReason(
8457
+ fn.section,
8458
+ binding.section,
8459
+ fn.registerReason
8460
+ );
8461
+ }
8462
+ });
8419
8463
  }
8420
- });
8464
+ }
8421
8465
  }
8422
8466
  }
8423
8467
  forEachSectionReverse((section) => {
@@ -8458,7 +8502,7 @@ function finalizeReferences() {
8458
8502
  }
8459
8503
  mergedReferences.clear();
8460
8504
  readsByExpression.clear();
8461
- readsByFn.clear();
8505
+ fnReadsByExpression.clear();
8462
8506
  }
8463
8507
  function getMaxOwnSourceOffset(intersection, section) {
8464
8508
  let scopeOffset;
@@ -8612,7 +8656,7 @@ var propsUtil = new Sorted(function compareProps(a, b) {
8612
8656
  var [getReadsByExpression] = createProgramState(
8613
8657
  () => /* @__PURE__ */ new Map()
8614
8658
  );
8615
- var [getReadsByFunction] = createProgramState(
8659
+ var [getFunctionReadsByExpression] = createProgramState(
8616
8660
  () => /* @__PURE__ */ new Map()
8617
8661
  );
8618
8662
  function addReadToExpression(root, binding) {
@@ -8628,11 +8672,14 @@ function addReadToExpression(root, binding) {
8628
8672
  push(readsByExpression.get(exprExtra), read)
8629
8673
  );
8630
8674
  if (fnRoot) {
8631
- const readsByFn = getReadsByFunction();
8675
+ const fnReadsByExpr = getFunctionReadsByExpression();
8676
+ let exprFnReads = fnReadsByExpr.get(exprExtra);
8677
+ if (!exprFnReads) {
8678
+ fnReadsByExpr.set(exprExtra, exprFnReads = /* @__PURE__ */ new Map());
8679
+ }
8632
8680
  const fnExtra = fnRoot.node.extra ??= {};
8633
- exprExtra.fnExtra = fnExtra;
8634
8681
  fnExtra.section = section;
8635
- readsByFn.set(fnExtra, push(readsByFn.get(fnExtra), read));
8682
+ exprFnReads.set(fnExtra, push(exprFnReads.get(fnExtra), read));
8636
8683
  }
8637
8684
  }
8638
8685
  function dropReferences(node) {
@@ -8768,14 +8815,38 @@ function getReadReplacement(node) {
8768
8815
  replacement = import_compiler35.types.identifier(binding.name);
8769
8816
  }
8770
8817
  } else if (read) {
8771
- replacement = toMemberExpression(
8772
- import_compiler35.types.identifier(read.binding.name),
8773
- Array.isArray(read.props) ? read.props[0] : read.props
8774
- );
8775
- if (Array.isArray(read.props)) {
8776
- for (let i = 1; i < read.props.length; i++) {
8777
- replacement = toMemberExpression(replacement, read.props[i]);
8818
+ const props = read.props ? Array.isArray(read.props) ? read.props.slice() : [read.props] : [];
8819
+ let curNode = node;
8820
+ let curBinding = read.binding;
8821
+ let replaceMember;
8822
+ replacement = import_compiler35.types.identifier(read.binding.name);
8823
+ while (props.length && (curNode.type === "MemberExpression" || curNode.type === "OptionalMemberExpression")) {
8824
+ const prop = props.pop();
8825
+ const memberProp = getMemberExpressionPropString(curNode);
8826
+ if (memberProp !== prop) break;
8827
+ replaceMember = curNode;
8828
+ curNode = curNode.object;
8829
+ }
8830
+ for (const prop of props) {
8831
+ if (curBinding) {
8832
+ curBinding = curBinding.propertyAliases.get(prop);
8833
+ }
8834
+ replacement = toMemberExpression(
8835
+ replacement,
8836
+ prop,
8837
+ !!curBinding?.nullable
8838
+ );
8839
+ }
8840
+ if (replaceMember) {
8841
+ if (read.binding.nullable && replaceMember.object.type !== replacement.type) {
8842
+ replaceMember.type = "OptionalMemberExpression";
8843
+ replaceMember.optional = true;
8778
8844
  }
8845
+ replaceMember.object = withPreviousLocation(
8846
+ replacement,
8847
+ replaceMember.object
8848
+ );
8849
+ replacement = void 0;
8779
8850
  }
8780
8851
  }
8781
8852
  return replacement && withPreviousLocation(replacement, node);
@@ -8804,13 +8875,70 @@ function pruneBinding(bindings, binding) {
8804
8875
  }
8805
8876
  return shouldPrune;
8806
8877
  }
8878
+ function resolveReferencedBindingsInFunction(refs, reads) {
8879
+ if (reads) {
8880
+ if (Array.isArray(reads)) {
8881
+ let referencedBindings;
8882
+ for (const read of reads) {
8883
+ referencedBindings = bindingUtil.add(
8884
+ referencedBindings,
8885
+ findClosestReference(read.binding, refs)
8886
+ );
8887
+ }
8888
+ return referencedBindings;
8889
+ } else {
8890
+ return findClosestReference(reads.binding, refs);
8891
+ }
8892
+ }
8893
+ }
8894
+ function findClosestReference(from, refs) {
8895
+ if (Array.isArray(refs)) {
8896
+ if (bindingUtil.has(refs, from)) {
8897
+ return from;
8898
+ }
8899
+ for (const ref of refs) {
8900
+ const closest = findClosestUpstream(from, ref);
8901
+ if (closest) return closest;
8902
+ }
8903
+ } else {
8904
+ const closest = findClosestUpstream(from, refs);
8905
+ if (closest) return closest;
8906
+ }
8907
+ }
8908
+ function findClosestUpstream(from, to) {
8909
+ let closest = from;
8910
+ do {
8911
+ if (closest === to) {
8912
+ return closest;
8913
+ }
8914
+ } while (closest = closest.upstreamAlias);
8915
+ }
8916
+ function getRootBindings(reads) {
8917
+ let rootRefs;
8918
+ let allBindings;
8919
+ for (const { binding } of reads) {
8920
+ allBindings = bindingUtil.add(allBindings, binding);
8921
+ }
8922
+ for (const { binding } of reads) {
8923
+ let alias = binding.upstreamAlias;
8924
+ while (alias) {
8925
+ if (bindingUtil.has(allBindings, alias)) break;
8926
+ alias = alias.upstreamAlias;
8927
+ }
8928
+ if (!alias) {
8929
+ rootRefs = bindingUtil.add(rootRefs, binding);
8930
+ }
8931
+ }
8932
+ return rootRefs;
8933
+ }
8807
8934
  function resolveReferencedBindings(expr, reads, intersectionsBySection) {
8808
8935
  let referencedBindings;
8809
8936
  if (Array.isArray(reads)) {
8937
+ const rootBindings = getRootBindings(reads);
8810
8938
  for (const read of reads) {
8811
8939
  let { binding } = read;
8812
8940
  if (read.node) {
8813
- const exprReference = (read.node.extra ??= {}).read ??= resolveExpressionReference(reads, binding, void 0);
8941
+ const exprReference = (read.node.extra ??= {}).read ??= resolveExpressionReference(rootBindings, binding);
8814
8942
  ({ binding } = (read.node.extra ??= {}).read = exprReference);
8815
8943
  }
8816
8944
  referencedBindings = bindingUtil.add(referencedBindings, binding);
@@ -8839,38 +8967,29 @@ function resolveReferencedBindings(expr, reads, intersectionsBySection) {
8839
8967
  }
8840
8968
  return referencedBindings;
8841
8969
  }
8842
- function resolveExpressionReference(reads, readBinding, readProps) {
8843
- const { upstreamAlias } = readBinding;
8844
- if (upstreamAlias && Array.isArray(reads)) {
8845
- const prop = getCanonicalProperty(readBinding);
8846
- const aliasProps = prop === void 0 ? readProps : push(readProps, prop);
8847
- for (const { binding } of reads) {
8848
- if (binding !== readBinding) {
8849
- let alias = upstreamAlias;
8850
- while (alias) {
8851
- if (binding === alias) {
8852
- return resolveExpressionReference(reads, alias, aliasProps);
8853
- }
8854
- alias = alias.upstreamAlias;
8855
- }
8856
- }
8970
+ function resolveExpressionReference(rootBindings, readBinding) {
8971
+ const upstreamRoot = readBinding.upstreamAlias && findClosestReference(readBinding.upstreamAlias, rootBindings);
8972
+ if (!upstreamRoot) {
8973
+ return createRead(readBinding, void 0);
8974
+ }
8975
+ let curBinding = readBinding;
8976
+ let props;
8977
+ while (curBinding !== upstreamRoot) {
8978
+ if (curBinding.property !== void 0) {
8979
+ props = push(props, curBinding.property);
8857
8980
  }
8981
+ curBinding = curBinding.upstreamAlias;
8858
8982
  }
8859
- return createRead(readBinding, readProps);
8983
+ if (Array.isArray(props)) {
8984
+ props.reverse();
8985
+ }
8986
+ return createRead(upstreamRoot, props);
8860
8987
  }
8861
8988
  function isSupersetSources(a, b) {
8862
8989
  if (!b.sources) return true;
8863
8990
  if (!a.sources) return false;
8864
8991
  return bindingUtil.isSuperset(a.sources.state, b.sources.state) && bindingUtil.isSuperset(a.sources.param, b.sources.param);
8865
8992
  }
8866
- function getCanonicalProperty(binding) {
8867
- if (binding.property !== void 0) {
8868
- return binding.property;
8869
- }
8870
- if (binding.upstreamAlias && binding.excludeProperties === void 0) {
8871
- return binding.upstreamAlias.property;
8872
- }
8873
- }
8874
8993
  function createRead(binding, props) {
8875
8994
  return { binding, props };
8876
8995
  }
@@ -49,9 +49,8 @@ export interface ParamBinding extends Binding {
49
49
  }
50
50
  export type ReferencedBindings = Opt<Binding>;
51
51
  export type Intersection = Many<Binding>;
52
- type FnExtra = (t.FunctionExpressionExtra | t.ArrowFunctionExpressionExtra | t.FunctionDeclarationExtra) & {
53
- section: Section;
54
- };
52
+ interface ReferencedFunctionExtra extends t.FunctionExtra, ReferencedExtra {
53
+ }
55
54
  declare module "@marko/compiler/dist/types" {
56
55
  interface NodeExtra {
57
56
  section?: Section;
@@ -69,7 +68,11 @@ declare module "@marko/compiler/dist/types" {
69
68
  [kIsInvoked]?: true;
70
69
  }
71
70
  interface FunctionExtra {
71
+ referencesScope?: boolean;
72
72
  referencedBindingsInFunction?: ReferencedBindings;
73
+ name?: string;
74
+ registerId?: string;
75
+ registerReason?: SerializeReason;
73
76
  }
74
77
  interface ArrowFunctionExpressionExtra extends FunctionExtra {
75
78
  }
@@ -109,22 +112,20 @@ export declare function getDebugName(binding: Binding): string;
109
112
  export declare function getDebugNames(refs: ReferencedBindings): string;
110
113
  export declare function getSectionInstancesAccessor(section: Section): string;
111
114
  export declare function getSectionInstancesAccessorLiteral(section: Section): t.StringLiteral | t.NumericLiteral | undefined;
112
- export declare function getReadReplacement(node: t.Identifier | t.MemberExpression | t.OptionalMemberExpression): t.Node | undefined;
115
+ export declare function getReadReplacement(node: t.Identifier | t.MemberExpression | t.OptionalMemberExpression): t.Expression | undefined;
113
116
  export interface ReferencedExtra extends t.NodeExtra {
114
117
  section: Section;
115
- fnExtra?: FnExtra;
116
118
  }
117
119
  export declare function isReferencedExtra(extra: t.NodeExtra | undefined): extra is ReferencedExtra;
118
120
  export interface AssignedBindingExtra extends ReferencedExtra {
119
121
  assignment: Binding;
122
+ assignmentFunction: ReferencedFunctionExtra;
120
123
  }
121
124
  export declare function isAssignedBindingExtra(extra: t.NodeExtra | undefined): extra is AssignedBindingExtra;
122
- export interface RegisteredFnExtra extends ReferencedExtra {
125
+ export interface RegisteredFnExtra extends ReferencedExtra, t.FunctionExtra {
126
+ name: string;
123
127
  registerId: string;
124
128
  registerReason: SerializeReason;
125
- name: string;
126
- referencesScope?: boolean;
127
- referencedBindingsInFunction: ReferencedBindings;
128
129
  }
129
130
  export declare function isRegisteredFnExtra(extra: t.NodeExtra | undefined): extra is RegisteredFnExtra;
130
131
  export declare function getCanonicalExtra<T extends t.NodeExtra>(extra: T): T;
@@ -1,22 +1,4 @@
1
1
  import { types as t } from "@marko/compiler";
2
- import { type SerializeReason } from "../util/serialize-reasons";
3
- declare module "@marko/compiler/dist/types" {
4
- interface FunctionDeclarationExtra {
5
- registerId?: string;
6
- registerReason?: SerializeReason;
7
- name?: string;
8
- }
9
- interface FunctionExpressionExtra {
10
- registerId?: string;
11
- registerReason?: SerializeReason;
12
- name?: string;
13
- }
14
- interface ArrowFunctionExpressionExtra {
15
- registerId?: string;
16
- registerReason?: SerializeReason;
17
- name?: string;
18
- }
19
- }
20
2
  declare const _default: {
21
3
  analyze(this: unknown, fn: t.NodePath<t.Function>): void;
22
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marko",
3
- "version": "6.0.94",
3
+ "version": "6.0.96",
4
4
  "description": "Optimized runtime for Marko templates.",
5
5
  "keywords": [
6
6
  "api",
@@ -48,7 +48,7 @@
48
48
  "build": "node -r ~ts ./scripts/bundle.ts"
49
49
  },
50
50
  "dependencies": {
51
- "@marko/compiler": "^5.39.40",
51
+ "@marko/compiler": "^5.39.41",
52
52
  "csstype": "^3.1.3",
53
53
  "magic-string": "^0.30.17"
54
54
  },