@marko/language-tools 2.5.28 → 2.5.29

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.
@@ -54,7 +54,7 @@ type Bindings = {
54
54
  */
55
55
  export declare function crawlProgramScope(parsed: Parsed, scriptParser: ScriptParser): [number, ...number[]] | [...number[], number] | undefined;
56
56
  export declare function getHoists(node: Node.Program): Repeatable<string>;
57
- export declare function getHoistSources(node: Node.ParentNode): Repeatable<string>;
57
+ export declare function getHoistSources(body: Node.ParentNode["body"]): Repeatable<string>;
58
58
  export declare function getMutatedVars(node: Node.ParentNode): Set<VarBinding> | undefined;
59
59
  export declare function isMutatedVar(node: Node.ParentNode, name: string): boolean;
60
60
  export declare function hasHoists(node: Node.ParentTag): boolean;
package/dist/index.js CHANGED
@@ -1117,6 +1117,7 @@ function crawlProgramScope(parsed, scriptParser) {
1117
1117
  }
1118
1118
  break;
1119
1119
  }
1120
+ curParent.hoists = true;
1120
1121
  if (curParent === programScope) {
1121
1122
  binding.hoisted = true;
1122
1123
  programScope.bindings[name] = {
@@ -1130,11 +1131,7 @@ function crawlProgramScope(parsed, scriptParser) {
1130
1131
  curParent = curParent.parent;
1131
1132
  }
1132
1133
  if (binding.hoisted) {
1133
- curParent = scope;
1134
- while (curParent && !curParent.hoists) {
1135
- curParent.hoists = true;
1136
- curParent = curParent.parent;
1137
- }
1134
+ scope.hoists = true;
1138
1135
  }
1139
1136
  }
1140
1137
  for (const [scope, nodes] of nodesToCheckForMutations) {
@@ -1327,10 +1324,10 @@ function getHoists(node) {
1327
1324
  }
1328
1325
  return result;
1329
1326
  }
1330
- function getHoistSources(node) {
1327
+ function getHoistSources(body) {
1331
1328
  let result;
1332
- if (node.body) {
1333
- const { bindings } = Scopes.get(node.body);
1329
+ if (body) {
1330
+ const { bindings } = Scopes.get(body);
1334
1331
  for (const key in bindings) {
1335
1332
  if (bindings[key].hoisted) {
1336
1333
  if (result) {
@@ -2150,7 +2147,6 @@ function ${templateName}() {
2150
2147
  // @ts-expect-error We expect the compiler to error because we are checking if the MarkoRun.Context is defined.
2151
2148
  (${varShared("error")}, ${this.#getCastedType("MarkoRun.Context")})
2152
2149
  );
2153
- ${varShared("noop")}({ ${this.#api !== RuntimeAPI.tags ? "component, state, out, " : ""}input, $global, $signal });
2154
2150
  `);
2155
2151
  const body = this.#processBody(program);
2156
2152
  if (body == null ? void 0 : body.content) {
@@ -2160,22 +2156,15 @@ function ${templateName}() {
2160
2156
  if (hoists) {
2161
2157
  this.#extractor.write("const ");
2162
2158
  this.#writeObjectKeys(hoists);
2163
- this.#extractor.write(` = ${varShared("readScopes")}({`);
2164
- for (const child of program.body) {
2165
- if (child.type === 1 /* Tag */) {
2166
- const renderId = this.#renderIds.get(child);
2167
- if (renderId !== void 0) {
2168
- this.#extractor.write(
2169
- `${varLocal("rendered_" + renderId)}${SEP_COMMA_SPACE}`
2170
- );
2171
- }
2172
- }
2173
- }
2174
- this.#extractor.write(`});
2175
- ${varShared("noop")}(`);
2176
- this.#writeObjectKeys(hoists);
2177
- this.#extractor.write(");\n");
2159
+ this.#extractor.write(
2160
+ " = " + this.#getBodyHoistScopeExpression(program.body)
2161
+ );
2178
2162
  }
2163
+ this.#extractor.write(
2164
+ `
2165
+ ;${varShared("noop")}({ ${hoists ? hoists.join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api !== RuntimeAPI.tags ? "component, state, out, " : ""}input, $global, $signal });
2166
+ `
2167
+ );
2179
2168
  if (didReturn) {
2180
2169
  this.#extractor.write(`return ${varLocal("return")}.return;
2181
2170
  }
@@ -2261,19 +2250,31 @@ ${varShared("noop")}(`);
2261
2250
  }
2262
2251
  }
2263
2252
  }
2264
- #writeReturn(returned, localBindings) {
2265
- if (!returned && !localBindings) {
2253
+ #writeReturn(returned, body) {
2254
+ const hoistSources = getHoistSources(body);
2255
+ const hoistScopes = this.#getBodyHoistScopeExpression(body);
2256
+ const hasHoists2 = !!(hoistScopes || hoistSources);
2257
+ if (!returned && !hasHoists2) {
2266
2258
  this.#extractor.write(`return ${varShared("voidReturn")};
2267
2259
  `);
2268
2260
  return;
2269
2261
  }
2270
2262
  this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2271
2263
  `);
2272
- if (localBindings) {
2273
- this.#extractor.write(`[Marko._.scope] = `);
2274
- this.#writeObjectKeys(localBindings);
2275
- this.#extractor.write(`;
2276
- `);
2264
+ if (hasHoists2) {
2265
+ this.#extractor.write("[Marko._.scope] = ");
2266
+ if (hoistSources) {
2267
+ if (hoistScopes) {
2268
+ this.#extractor.write(`{ ...${hoistScopes}, ...`);
2269
+ this.#writeObjectKeys(hoistSources);
2270
+ this.#extractor.write(" }");
2271
+ } else {
2272
+ this.#writeObjectKeys(hoistSources);
2273
+ }
2274
+ } else {
2275
+ this.#extractor.write(hoistScopes);
2276
+ }
2277
+ this.#extractor.write(";\n");
2277
2278
  }
2278
2279
  this.#extractor.write(`declare return: Return;
2279
2280
  constructor(_?: Return) {}
@@ -2318,7 +2319,7 @@ constructor(_?: Return) {}
2318
2319
  ).write(") {\n");
2319
2320
  const ifBody = this.#processBody(child);
2320
2321
  if (ifBody == null ? void 0 : ifBody.content) {
2321
- const localBindings = getHoistSources(child);
2322
+ const localBindings = getHoistSources(child.body);
2322
2323
  this.#writeChildren(child, ifBody.content, true);
2323
2324
  if (localBindings) {
2324
2325
  this.#extractor.write("return {\nscope:");
@@ -2340,7 +2341,7 @@ constructor(_?: Return) {}
2340
2341
  }
2341
2342
  const alternateBody = this.#processBody(node);
2342
2343
  if (alternateBody == null ? void 0 : alternateBody.content) {
2343
- const localBindings = getHoistSources(node);
2344
+ const localBindings = getHoistSources(node.body);
2344
2345
  this.#writeChildren(node, alternateBody.content, true);
2345
2346
  if (localBindings) {
2346
2347
  this.#extractor.write("return {\nscope:");
@@ -2383,10 +2384,7 @@ constructor(_?: Return) {}
2383
2384
  if (body == null ? void 0 : body.content) {
2384
2385
  this.#writeChildren(child, body.content);
2385
2386
  }
2386
- this.#writeReturn(
2387
- void 0,
2388
- (body == null ? void 0 : body.content) ? getHoistSources(child) : void 0
2389
- );
2387
+ this.#writeReturn(void 0, (body == null ? void 0 : body.content) && child.body);
2390
2388
  this.#extractor.write("\n});\n");
2391
2389
  break;
2392
2390
  }
@@ -2905,7 +2903,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
2905
2903
  }
2906
2904
  this.#writeReturn(
2907
2905
  didReturn ? `${varLocal("return")}.return` : void 0,
2908
- getHoistSources(tag)
2906
+ tag.body
2909
2907
  );
2910
2908
  if (tag.params) {
2911
2909
  this.#extractor.write("})");
@@ -3221,6 +3219,35 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
3221
3219
  }
3222
3220
  return renderId;
3223
3221
  }
3222
+ #getBodyHoistScopeExpression(body) {
3223
+ let hoistIds;
3224
+ if (body) {
3225
+ for (const child of body) {
3226
+ if (child.type === 1 /* Tag */) {
3227
+ const renderId = this.#renderIds.get(child);
3228
+ if (renderId !== void 0 && hasHoists(child)) {
3229
+ if (hoistIds) {
3230
+ hoistIds.push(renderId);
3231
+ } else {
3232
+ hoistIds = [renderId];
3233
+ }
3234
+ }
3235
+ }
3236
+ }
3237
+ }
3238
+ if (hoistIds) {
3239
+ if (hoistIds.length === 1) {
3240
+ return `${varLocal("rendered_" + hoistIds[0])}.scope`;
3241
+ }
3242
+ let result = `${varShared("readScopes")}({ `;
3243
+ let sep = "";
3244
+ for (const renderId of hoistIds) {
3245
+ result += sep + `${varLocal("rendered_" + renderId)}`;
3246
+ sep = SEP_COMMA_SPACE;
3247
+ }
3248
+ return result + " })";
3249
+ }
3250
+ }
3224
3251
  #ensureTagId(tag) {
3225
3252
  let tagId = this.#tagIds.get(tag);
3226
3253
  if (!tagId) {
package/dist/index.mjs CHANGED
@@ -1077,6 +1077,7 @@ function crawlProgramScope(parsed, scriptParser) {
1077
1077
  }
1078
1078
  break;
1079
1079
  }
1080
+ curParent.hoists = true;
1080
1081
  if (curParent === programScope) {
1081
1082
  binding.hoisted = true;
1082
1083
  programScope.bindings[name] = {
@@ -1090,11 +1091,7 @@ function crawlProgramScope(parsed, scriptParser) {
1090
1091
  curParent = curParent.parent;
1091
1092
  }
1092
1093
  if (binding.hoisted) {
1093
- curParent = scope;
1094
- while (curParent && !curParent.hoists) {
1095
- curParent.hoists = true;
1096
- curParent = curParent.parent;
1097
- }
1094
+ scope.hoists = true;
1098
1095
  }
1099
1096
  }
1100
1097
  for (const [scope, nodes] of nodesToCheckForMutations) {
@@ -1287,10 +1284,10 @@ function getHoists(node) {
1287
1284
  }
1288
1285
  return result;
1289
1286
  }
1290
- function getHoistSources(node) {
1287
+ function getHoistSources(body) {
1291
1288
  let result;
1292
- if (node.body) {
1293
- const { bindings } = Scopes.get(node.body);
1289
+ if (body) {
1290
+ const { bindings } = Scopes.get(body);
1294
1291
  for (const key in bindings) {
1295
1292
  if (bindings[key].hoisted) {
1296
1293
  if (result) {
@@ -2113,7 +2110,6 @@ function ${templateName}() {
2113
2110
  // @ts-expect-error We expect the compiler to error because we are checking if the MarkoRun.Context is defined.
2114
2111
  (${varShared("error")}, ${this.#getCastedType("MarkoRun.Context")})
2115
2112
  );
2116
- ${varShared("noop")}({ ${this.#api !== RuntimeAPI.tags ? "component, state, out, " : ""}input, $global, $signal });
2117
2113
  `);
2118
2114
  const body = this.#processBody(program);
2119
2115
  if (body == null ? void 0 : body.content) {
@@ -2123,22 +2119,15 @@ function ${templateName}() {
2123
2119
  if (hoists) {
2124
2120
  this.#extractor.write("const ");
2125
2121
  this.#writeObjectKeys(hoists);
2126
- this.#extractor.write(` = ${varShared("readScopes")}({`);
2127
- for (const child of program.body) {
2128
- if (child.type === 1 /* Tag */) {
2129
- const renderId = this.#renderIds.get(child);
2130
- if (renderId !== void 0) {
2131
- this.#extractor.write(
2132
- `${varLocal("rendered_" + renderId)}${SEP_COMMA_SPACE}`
2133
- );
2134
- }
2135
- }
2136
- }
2137
- this.#extractor.write(`});
2138
- ${varShared("noop")}(`);
2139
- this.#writeObjectKeys(hoists);
2140
- this.#extractor.write(");\n");
2122
+ this.#extractor.write(
2123
+ " = " + this.#getBodyHoistScopeExpression(program.body)
2124
+ );
2141
2125
  }
2126
+ this.#extractor.write(
2127
+ `
2128
+ ;${varShared("noop")}({ ${hoists ? hoists.join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api !== RuntimeAPI.tags ? "component, state, out, " : ""}input, $global, $signal });
2129
+ `
2130
+ );
2142
2131
  if (didReturn) {
2143
2132
  this.#extractor.write(`return ${varLocal("return")}.return;
2144
2133
  }
@@ -2224,19 +2213,31 @@ ${varShared("noop")}(`);
2224
2213
  }
2225
2214
  }
2226
2215
  }
2227
- #writeReturn(returned, localBindings) {
2228
- if (!returned && !localBindings) {
2216
+ #writeReturn(returned, body) {
2217
+ const hoistSources = getHoistSources(body);
2218
+ const hoistScopes = this.#getBodyHoistScopeExpression(body);
2219
+ const hasHoists2 = !!(hoistScopes || hoistSources);
2220
+ if (!returned && !hasHoists2) {
2229
2221
  this.#extractor.write(`return ${varShared("voidReturn")};
2230
2222
  `);
2231
2223
  return;
2232
2224
  }
2233
2225
  this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2234
2226
  `);
2235
- if (localBindings) {
2236
- this.#extractor.write(`[Marko._.scope] = `);
2237
- this.#writeObjectKeys(localBindings);
2238
- this.#extractor.write(`;
2239
- `);
2227
+ if (hasHoists2) {
2228
+ this.#extractor.write("[Marko._.scope] = ");
2229
+ if (hoistSources) {
2230
+ if (hoistScopes) {
2231
+ this.#extractor.write(`{ ...${hoistScopes}, ...`);
2232
+ this.#writeObjectKeys(hoistSources);
2233
+ this.#extractor.write(" }");
2234
+ } else {
2235
+ this.#writeObjectKeys(hoistSources);
2236
+ }
2237
+ } else {
2238
+ this.#extractor.write(hoistScopes);
2239
+ }
2240
+ this.#extractor.write(";\n");
2240
2241
  }
2241
2242
  this.#extractor.write(`declare return: Return;
2242
2243
  constructor(_?: Return) {}
@@ -2281,7 +2282,7 @@ constructor(_?: Return) {}
2281
2282
  ).write(") {\n");
2282
2283
  const ifBody = this.#processBody(child);
2283
2284
  if (ifBody == null ? void 0 : ifBody.content) {
2284
- const localBindings = getHoistSources(child);
2285
+ const localBindings = getHoistSources(child.body);
2285
2286
  this.#writeChildren(child, ifBody.content, true);
2286
2287
  if (localBindings) {
2287
2288
  this.#extractor.write("return {\nscope:");
@@ -2303,7 +2304,7 @@ constructor(_?: Return) {}
2303
2304
  }
2304
2305
  const alternateBody = this.#processBody(node);
2305
2306
  if (alternateBody == null ? void 0 : alternateBody.content) {
2306
- const localBindings = getHoistSources(node);
2307
+ const localBindings = getHoistSources(node.body);
2307
2308
  this.#writeChildren(node, alternateBody.content, true);
2308
2309
  if (localBindings) {
2309
2310
  this.#extractor.write("return {\nscope:");
@@ -2346,10 +2347,7 @@ constructor(_?: Return) {}
2346
2347
  if (body == null ? void 0 : body.content) {
2347
2348
  this.#writeChildren(child, body.content);
2348
2349
  }
2349
- this.#writeReturn(
2350
- void 0,
2351
- (body == null ? void 0 : body.content) ? getHoistSources(child) : void 0
2352
- );
2350
+ this.#writeReturn(void 0, (body == null ? void 0 : body.content) && child.body);
2353
2351
  this.#extractor.write("\n});\n");
2354
2352
  break;
2355
2353
  }
@@ -2868,7 +2866,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
2868
2866
  }
2869
2867
  this.#writeReturn(
2870
2868
  didReturn ? `${varLocal("return")}.return` : void 0,
2871
- getHoistSources(tag)
2869
+ tag.body
2872
2870
  );
2873
2871
  if (tag.params) {
2874
2872
  this.#extractor.write("})");
@@ -3184,6 +3182,35 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
3184
3182
  }
3185
3183
  return renderId;
3186
3184
  }
3185
+ #getBodyHoistScopeExpression(body) {
3186
+ let hoistIds;
3187
+ if (body) {
3188
+ for (const child of body) {
3189
+ if (child.type === 1 /* Tag */) {
3190
+ const renderId = this.#renderIds.get(child);
3191
+ if (renderId !== void 0 && hasHoists(child)) {
3192
+ if (hoistIds) {
3193
+ hoistIds.push(renderId);
3194
+ } else {
3195
+ hoistIds = [renderId];
3196
+ }
3197
+ }
3198
+ }
3199
+ }
3200
+ }
3201
+ if (hoistIds) {
3202
+ if (hoistIds.length === 1) {
3203
+ return `${varLocal("rendered_" + hoistIds[0])}.scope`;
3204
+ }
3205
+ let result = `${varShared("readScopes")}({ `;
3206
+ let sep = "";
3207
+ for (const renderId of hoistIds) {
3208
+ result += sep + `${varLocal("rendered_" + renderId)}`;
3209
+ sep = SEP_COMMA_SPACE;
3210
+ }
3211
+ return result + " })";
3212
+ }
3213
+ }
3187
3214
  #ensureTagId(tag) {
3188
3215
  let tagId = this.#tagIds.get(tag);
3189
3216
  if (!tagId) {
@@ -170,7 +170,7 @@ declare global {
170
170
  >(
171
171
  input: {
172
172
  of: Value | false | void | null;
173
- by?: (item: Item, index: number) => string;
173
+ by?: ((item: Item, index: number) => string) | string;
174
174
  },
175
175
  content: BodyContent,
176
176
  ): ReturnAndScope<BodyContentScope<BodyContent>, void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@marko/language-tools",
3
3
  "description": "Marko Language Tools",
4
- "version": "2.5.28",
4
+ "version": "2.5.29",
5
5
  "bugs": "https://github.com/marko-js/language-server/issues/new?template=Bug_report.md",
6
6
  "peerDependencies": {
7
7
  "@marko/compiler": "^5.28.4"