wesl 0.6.1 → 0.6.2

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.
Files changed (62) hide show
  1. package/dist/index.js +369 -276
  2. package/dist/index.js.map +1 -1
  3. package/dist/minified.js +1176 -1102
  4. package/dist/minified.js.map +1 -1
  5. package/dist/tools/packages/wesl/src/BindIdents.d.ts +3 -0
  6. package/dist/tools/packages/wesl/src/ClickableError.d.ts +22 -0
  7. package/dist/tools/packages/wesl/src/LinkedWesl.d.ts +1 -1
  8. package/dist/tools/packages/wesl/src/Linker.d.ts +1 -1
  9. package/dist/tools/packages/wesl/src/Util.d.ts +1 -1
  10. package/dist/tools/packages/wesl/src/WESLCollect.d.ts +2 -2
  11. package/dist/tools/packages/wesl/src/WeslDevice.d.ts +0 -8
  12. package/dist/tools/packages/wesl/src/index.d.ts +1 -0
  13. package/dist/tools/packages/wesl/src/parse/WeslStream.d.ts +1 -0
  14. package/dist/tools/packages/wesl/src/test/TestUtil.d.ts +1 -1
  15. package/package.json +6 -6
  16. package/src/AbstractElems.ts +2 -2
  17. package/src/BindIdents.ts +67 -42
  18. package/src/ClickableError.ts +128 -0
  19. package/src/Conditions.ts +6 -6
  20. package/src/FlattenTreeImport.ts +2 -2
  21. package/src/LinkedWesl.ts +11 -11
  22. package/src/Linker.ts +15 -14
  23. package/src/LinkerUtil.ts +2 -2
  24. package/src/LiveDeclarations.ts +1 -1
  25. package/src/LowerAndEmit.ts +42 -31
  26. package/src/Mangler.ts +3 -3
  27. package/src/ParseWESL.ts +12 -6
  28. package/src/ParsedRegistry.ts +6 -6
  29. package/src/PathUtil.ts +2 -2
  30. package/src/RawEmit.ts +5 -5
  31. package/src/Reflection.ts +12 -10
  32. package/src/Scope.ts +7 -3
  33. package/src/TransformBindingStructs.ts +17 -17
  34. package/src/Util.ts +3 -3
  35. package/src/WESLCollect.ts +33 -27
  36. package/src/WeslDevice.ts +6 -84
  37. package/src/debug/ASTtoString.ts +12 -11
  38. package/src/debug/ImportToString.ts +3 -3
  39. package/src/debug/ScopeToString.ts +2 -1
  40. package/src/index.ts +1 -0
  41. package/src/parse/ImportGrammar.ts +13 -7
  42. package/src/parse/WeslBaseGrammar.ts +5 -2
  43. package/src/parse/WeslExpression.ts +30 -30
  44. package/src/parse/WeslGrammar.ts +192 -159
  45. package/src/parse/WeslStream.ts +8 -7
  46. package/src/test/BindWESL.test.ts +2 -2
  47. package/src/test/ConditionalTranslationCases.test.ts +39 -39
  48. package/src/test/ErrorLogging.test.ts +3 -3
  49. package/src/test/Expression.test.ts +3 -3
  50. package/src/test/FlattenTreeImport.test.ts +1 -1
  51. package/src/test/ImportCases.test.ts +40 -39
  52. package/src/test/ImportSyntaxCases.test.ts +1 -1
  53. package/src/test/Linker.test.ts +1 -1
  54. package/src/test/ParseWESL.test.ts +40 -16
  55. package/src/test/Reflection.test.ts +8 -8
  56. package/src/test/ScopeWESL.test.ts +2 -2
  57. package/src/test/TestLink.ts +6 -6
  58. package/src/test/TestUtil.ts +9 -9
  59. package/src/test/Tokenizer.test.ts +1 -1
  60. package/src/test/TransformBindingStructs.test.ts +1 -1
  61. package/src/test/WeslDevice.test.ts +6 -6
  62. package/src/vlq/vlq.ts +4 -4
package/dist/index.js CHANGED
@@ -57,12 +57,10 @@ function logInternalSrc(log2, src, pos, ...msgs) {
57
57
  log2(caret);
58
58
  }
59
59
  function carets(linePos, linePos2) {
60
- const firstCaret = " ".repeat(linePos) + "^";
61
- let secondCaret = "";
62
- if (linePos2 && linePos2 > linePos) {
63
- secondCaret = " ".repeat(linePos2 - linePos - 1) + "^";
64
- }
65
- return firstCaret + secondCaret;
60
+ const indent = " ".repeat(linePos);
61
+ const numCarets = linePos2 ? linePos2 - linePos : 1;
62
+ const carets2 = "^".repeat(numCarets);
63
+ return indent + carets2;
66
64
  }
67
65
  const startCache = /* @__PURE__ */ new Map();
68
66
  function srcLine(src, position) {
@@ -294,6 +292,18 @@ function opt(arg) {
294
292
  }
295
293
  );
296
294
  }
295
+ function not(arg) {
296
+ const p = parserArg(arg);
297
+ return parser("not", function _not(state) {
298
+ const pos = state.stream.checkpoint();
299
+ const result = p._run(state);
300
+ if (result === null) {
301
+ state.stream.reset(pos);
302
+ return { value: true };
303
+ }
304
+ return null;
305
+ });
306
+ }
297
307
  function repeat(arg) {
298
308
  const p = parserArg(arg);
299
309
  return parser("repeat", repeatWhileFilter(p));
@@ -1138,6 +1148,112 @@ function errorHighlight(source, span2) {
1138
1148
  " ".repeat(linePos) + "^".repeat(caretCount)
1139
1149
  ];
1140
1150
  }
1151
+ /*!
1152
+ Copyright (c) 2017-2021 [these people](https://github.com/Rich-Harris/vlq/graphs/contributors)
1153
+
1154
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1155
+
1156
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1157
+
1158
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1159
+ */
1160
+ const integer_to_char = {};
1161
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split("").forEach((char, i) => {
1162
+ integer_to_char[i] = char;
1163
+ });
1164
+ function encodeVlq(value) {
1165
+ if (typeof value === "number") {
1166
+ return encode_integer(value);
1167
+ }
1168
+ let result = "";
1169
+ for (let i = 0; i < value.length; i += 1) {
1170
+ result += encode_integer(value[i]);
1171
+ }
1172
+ return result;
1173
+ }
1174
+ function encode_integer(num) {
1175
+ let result = "";
1176
+ if (num < 0) {
1177
+ num = -num << 1 | 1;
1178
+ } else {
1179
+ num <<= 1;
1180
+ }
1181
+ do {
1182
+ let clamped = num & 31;
1183
+ num >>>= 5;
1184
+ if (num > 0) {
1185
+ clamped |= 32;
1186
+ }
1187
+ result += integer_to_char[clamped];
1188
+ } while (num > 0);
1189
+ return result;
1190
+ }
1191
+ function throwClickableError(params) {
1192
+ const { url, text: text2, lineNumber, lineColumn, length, error } = params;
1193
+ const mappings = encodeVlq([
1194
+ 0,
1195
+ 0,
1196
+ Math.max(0, lineNumber - 1),
1197
+ Math.max(0, lineColumn - 1)
1198
+ ]) + "," + // Sadly no browser makes use of this info to map the error properly
1199
+ encodeVlq([
1200
+ 18,
1201
+ // Arbitrary number that is high enough
1202
+ 0,
1203
+ Math.max(0, lineNumber - 1),
1204
+ Math.max(0, lineColumn - 1) + length
1205
+ ]);
1206
+ const sourceMap = {
1207
+ version: 3,
1208
+ file: null,
1209
+ sources: [url],
1210
+ sourcesContent: [text2 ?? null],
1211
+ names: [],
1212
+ mappings
1213
+ };
1214
+ let generatedCode = `throw new Error(${JSON.stringify(error.message + "")})`;
1215
+ generatedCode += "\n//# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
1216
+ generatedCode += "\n//# sourceURL=" + sourceMap.sources[0];
1217
+ let oldLimit = 0;
1218
+ if ("stackTraceLimit" in Error) {
1219
+ oldLimit = Error.stackTraceLimit;
1220
+ Error.stackTraceLimit = 1;
1221
+ }
1222
+ try {
1223
+ (0, eval)(generatedCode);
1224
+ } catch (e) {
1225
+ if ("stackTraceLimit" in Error) {
1226
+ Error.stackTraceLimit = oldLimit;
1227
+ }
1228
+ error.message = "";
1229
+ throw e;
1230
+ }
1231
+ }
1232
+ function failIdent(ident2, msg) {
1233
+ const { refIdentElem, originalName } = ident2;
1234
+ const baseMessage = msg ?? `'${originalName}'`;
1235
+ if (refIdentElem) {
1236
+ failIdentElem(refIdentElem, baseMessage);
1237
+ } else {
1238
+ throw new Error(baseMessage);
1239
+ }
1240
+ }
1241
+ function failIdentElem(identElem, msg = "") {
1242
+ const { srcModule, start, end } = identElem;
1243
+ const { debugFilePath, src } = srcModule;
1244
+ const detailedMessage = `${msg} in file: ${debugFilePath}`;
1245
+ srcLog(src, [start, end], detailedMessage);
1246
+ const [lineNumber, lineColumn] = offsetToLineNumber(start, src);
1247
+ const length = end - start;
1248
+ throwClickableError({
1249
+ url: debugFilePath,
1250
+ text: src,
1251
+ lineNumber,
1252
+ lineColumn,
1253
+ length,
1254
+ error: new Error(detailedMessage)
1255
+ });
1256
+ }
1141
1257
  function elementValid(elem, conditions) {
1142
1258
  const attributes = elem.attributes;
1143
1259
  if (!attributes) return true;
@@ -1159,10 +1275,10 @@ function evaluateIfAttribute(ifAttribute, conditions) {
1159
1275
  }
1160
1276
  function evaluateIfExpression(expression2, conditions) {
1161
1277
  const { kind: kind2 } = expression2;
1162
- if (kind2 == "unary-expression") {
1278
+ if (kind2 === "unary-expression") {
1163
1279
  assertThatDebug(expression2.operator.value === "!");
1164
1280
  return !evaluateIfExpression(expression2.expression, conditions);
1165
- } else if (kind2 == "binary-expression") {
1281
+ } else if (kind2 === "binary-expression") {
1166
1282
  const op = expression2.operator.value;
1167
1283
  const leftResult = evaluateIfExpression(expression2.left, conditions);
1168
1284
  if (op === "||") {
@@ -1172,10 +1288,10 @@ function evaluateIfExpression(expression2, conditions) {
1172
1288
  } else {
1173
1289
  assertUnreachable(op);
1174
1290
  }
1175
- } else if (kind2 == "literal") {
1291
+ } else if (kind2 === "literal") {
1176
1292
  const { value } = expression2;
1177
1293
  return value === "true";
1178
- } else if (kind2 == "parenthesized-expression") {
1294
+ } else if (kind2 === "parenthesized-expression") {
1179
1295
  return evaluateIfExpression(expression2.expression, conditions);
1180
1296
  } else if (kind2 === "translate-time-feature") {
1181
1297
  return conditions[expression2.name];
@@ -1452,7 +1568,7 @@ function importElem(cc) {
1452
1568
  function addToOpenElem(cc, elem) {
1453
1569
  const weslContext = cc.app.context;
1454
1570
  const { openElems } = weslContext;
1455
- if (openElems && openElems.length) {
1571
+ if (openElems == null ? void 0 : openElems.length) {
1456
1572
  const open = openElems[openElems.length - 1];
1457
1573
  open.contents.push(elem);
1458
1574
  }
@@ -1616,7 +1732,7 @@ const fnCollect = collectElem(
1616
1732
  mergeScope(mergedScope, bodyScope);
1617
1733
  const filtered = [];
1618
1734
  for (const e of fnScope.contents) {
1619
- if (e === headerScope || e == returnScope) {
1735
+ if (e === headerScope || e === returnScope) {
1620
1736
  continue;
1621
1737
  } else if (e === bodyScope) {
1622
1738
  filtered.push(mergedScope);
@@ -1724,7 +1840,7 @@ const typeRefCollect = collectElem(
1724
1840
  // @ts-ignore
1725
1841
  (cc, openElem) => {
1726
1842
  var _a, _b;
1727
- let templateParamsTemp = (_a = cc.tags.templateParam) == null ? void 0 : _a.flat(3);
1843
+ const templateParamsTemp = (_a = cc.tags.templateParam) == null ? void 0 : _a.flat(3);
1728
1844
  const typeRef = (_b = cc.tags.typeRefName) == null ? void 0 : _b[0];
1729
1845
  const name2 = typeof typeRef === "string" ? typeRef : typeRef.ident;
1730
1846
  const partElem = {
@@ -1760,7 +1876,7 @@ const memberRefCollect = collectElem(
1760
1876
  "memberRef",
1761
1877
  (cc, openElem) => {
1762
1878
  const { component, structRef, extra_components } = cc.tags;
1763
- const member = component[0];
1879
+ const member = component == null ? void 0 : component[0];
1764
1880
  const name2 = structRef == null ? void 0 : structRef.flat()[0];
1765
1881
  const extraComponents = extra_components == null ? void 0 : extra_components.flat()[0];
1766
1882
  const partElem = {
@@ -1854,8 +1970,11 @@ function coverWithText(cc, elem) {
1854
1970
  }
1855
1971
  }
1856
1972
  const word = kind("word");
1857
- kind("keyword");
1858
- const qualified_ident = withSepPlus("::", or(word, "package", "super"));
1973
+ const keyword = kind("keyword");
1974
+ const qualified_ident = withSepPlus(
1975
+ "::",
1976
+ or(word, keyword, "package", "super")
1977
+ );
1859
1978
  const number = kind("number");
1860
1979
  function makeStatement(segments, finalSegment) {
1861
1980
  return { kind: "import-statement", segments, finalSegment };
@@ -1877,8 +1996,10 @@ function prependSegments(segments, statement2) {
1877
1996
  return statement2;
1878
1997
  }
1879
1998
  let import_collection = null;
1999
+ const segment_blacklist = or("super", "package", "import", "as");
2000
+ const packageWord = preceded(not(segment_blacklist), or(word, keyword));
1880
2001
  const import_path_or_item = seq(
1881
- word,
2002
+ packageWord,
1882
2003
  or(
1883
2004
  preceded(
1884
2005
  "::",
@@ -2020,7 +2141,7 @@ class WeslStream {
2020
2141
  this.stream.reset(this.skipBlockComment(token2.span[1]));
2021
2142
  }
2022
2143
  } else if (kind2 === "word") {
2023
- let returnToken = token2;
2144
+ const returnToken = token2;
2024
2145
  if (keywordOrReserved.has(token2.text)) {
2025
2146
  returnToken.kind = "keyword";
2026
2147
  }
@@ -2108,7 +2229,7 @@ class WeslStream {
2108
2229
  if (nextToken.text === "<") {
2109
2230
  pendingCounter += 1;
2110
2231
  } else if (nextToken.text[0] === ">") {
2111
- if (nextToken.text === ">" || nextToken.text == ">=") {
2232
+ if (nextToken.text === ">" || nextToken.text === ">=") {
2112
2233
  pendingCounter -= 1;
2113
2234
  } else if (nextToken.text === ">>=" || nextToken.text === ">>") {
2114
2235
  pendingCounter -= 2;
@@ -2277,9 +2398,9 @@ const expressionParser = (inTemplate) => {
2277
2398
  )
2278
2399
  );
2279
2400
  };
2280
- let maybe_template = false;
2401
+ const maybe_template = false;
2281
2402
  const expression = expressionParser(maybe_template);
2282
- let is_template = true;
2403
+ const is_template = true;
2283
2404
  const template_arg_expression = expressionParser(is_template);
2284
2405
  const std_type_specifier = seq(
2285
2406
  qualified_ident.collect(refIdent, "typeRefName"),
@@ -2317,11 +2438,25 @@ const special_attribute = tagScope(
2317
2438
  "@",
2318
2439
  or(
2319
2440
  // These attributes have no arguments
2320
- or("compute", "const", "fragment", "invariant", "must_use", "vertex").map((name2) => makeStandardAttribute([name2, []])),
2441
+ or("compute", "const", "fragment", "invariant", "must_use", "vertex").map(
2442
+ (name2) => makeStandardAttribute([name2, []])
2443
+ ),
2321
2444
  // These attributes have arguments, but the argument doesn't have any identifiers
2322
- preceded("interpolate", req(delimited("(", name_list, ")"), "invalid @interpolate, expected '('")).map(makeInterpolateAttribute),
2323
- preceded("builtin", req(delimited("(", name, ")"), "invalid @builtin, expected '('")).map(makeBuiltinAttribute),
2324
- preceded("diagnostic", req(diagnostic_control, "invalid @diagnostic, expected '('")).map(makeDiagnosticAttribute)
2445
+ preceded(
2446
+ "interpolate",
2447
+ req(
2448
+ delimited("(", name_list, ")"),
2449
+ "invalid @interpolate, expected '('"
2450
+ )
2451
+ ).map(makeInterpolateAttribute),
2452
+ preceded(
2453
+ "builtin",
2454
+ req(delimited("(", name, ")"), "invalid @builtin, expected '('")
2455
+ ).map(makeBuiltinAttribute),
2456
+ preceded(
2457
+ "diagnostic",
2458
+ req(diagnostic_control, "invalid @diagnostic, expected '('")
2459
+ ).map(makeDiagnosticAttribute)
2325
2460
  ).ptag("attr_variant")
2326
2461
  ).collect(specialAttribute)
2327
2462
  );
@@ -2357,7 +2492,7 @@ const normal_attribute = tagScope(
2357
2492
  ),
2358
2493
  // Everything else is also a normal attribute, optional expression list
2359
2494
  seq(
2360
- // we don't want this to interfere with if_attribute,
2495
+ // we don't want this to interfere with if_attribute,
2361
2496
  // but not("if") isn't necessary for now, since 'if' is a keyword, not a word
2362
2497
  word.ptag("name"),
2363
2498
  opt(() => attribute_argument_list)
@@ -2374,10 +2509,9 @@ const attribute_argument_list = delimited(
2374
2509
  ),
2375
2510
  req(")", "invalid attribute arguments, expected ')'")
2376
2511
  );
2377
- const attribute_no_if = or(
2378
- special_attribute,
2379
- normal_attribute
2380
- ).ctag("attribute");
2512
+ const attribute_no_if = or(special_attribute, normal_attribute).ctag(
2513
+ "attribute"
2514
+ );
2381
2515
  const attribute_incl_if = or(
2382
2516
  if_attribute,
2383
2517
  special_attribute,
@@ -2418,7 +2552,10 @@ const struct_member = tagScope(
2418
2552
  ).collect(collectStructMember)
2419
2553
  ).ctag("members");
2420
2554
  const struct_decl = seq(
2421
- weslExtension(opt_attributes).collect((cc) => cc.tags.attribute, "attributes"),
2555
+ weslExtension(opt_attributes).collect(
2556
+ (cc) => cc.tags.attribute,
2557
+ "attributes"
2558
+ ),
2422
2559
  "struct",
2423
2560
  req(globalTypeNameDecl, "invalid struct, expected name"),
2424
2561
  seq(
@@ -2436,7 +2573,12 @@ const fnParam = tagScope(
2436
2573
  seq(
2437
2574
  opt_attributes.collect((cc) => cc.tags.attribute, "attributes"),
2438
2575
  word.collect(declCollect, "decl_elem"),
2439
- opt(seq(":", req(type_specifier, "invalid fn parameter, expected type specifier"))).collect(typedDecl, "param_name")
2576
+ opt(
2577
+ seq(
2578
+ ":",
2579
+ req(type_specifier, "invalid fn parameter, expected type specifier")
2580
+ )
2581
+ ).collect(typedDecl, "param_name")
2440
2582
  ).collect(collectFnParam)
2441
2583
  ).ctag("fn_param");
2442
2584
  const fnParamList = seq("(", withSep(",", fnParam), ")");
@@ -2628,16 +2770,10 @@ const regular_statement = or(
2628
2770
  )
2629
2771
  );
2630
2772
  const conditional_statement = tagScope(
2631
- seq(
2632
- opt_attributes,
2633
- regular_statement
2634
- ).collect(statementCollect).collect(partialScopeCollect)
2773
+ seq(opt_attributes, regular_statement).collect(statementCollect).collect(partialScopeCollect)
2635
2774
  );
2636
2775
  const unconditional_statement = tagScope(
2637
- seq(
2638
- opt_attributes_no_if,
2639
- regular_statement
2640
- )
2776
+ seq(opt_attributes_no_if, regular_statement)
2641
2777
  );
2642
2778
  const statement = or(
2643
2779
  compound_statement,
@@ -2646,10 +2782,7 @@ const statement = or(
2646
2782
  );
2647
2783
  const lhs_expression = or(
2648
2784
  simple_component_reference,
2649
- seq(
2650
- qualified_ident.collect(refIdent),
2651
- opt(component_or_swizzle)
2652
- ),
2785
+ seq(qualified_ident.collect(refIdent), opt(component_or_swizzle)),
2653
2786
  seq(
2654
2787
  "(",
2655
2788
  () => lhs_expression,
@@ -2665,7 +2798,12 @@ const variable_or_value_statement = tagScope(
2665
2798
  or(
2666
2799
  // Also covers the = expression case
2667
2800
  local_variable_decl,
2668
- seq("const", req_optionally_typed_ident, req("=", "invalid const declaration, expected '='"), expression),
2801
+ seq(
2802
+ "const",
2803
+ req_optionally_typed_ident,
2804
+ req("=", "invalid const declaration, expected '='"),
2805
+ expression
2806
+ ),
2669
2807
  seq(
2670
2808
  "let",
2671
2809
  req_optionally_typed_ident,
@@ -2684,22 +2822,24 @@ const variable_updating_statement = or(
2684
2822
  seq("_", "=", expression)
2685
2823
  );
2686
2824
  const fn_decl = seq(
2687
- tagScope(
2688
- opt_attributes.collect((cc) => cc.tags.attribute || [])
2689
- ).ctag("fn_attributes"),
2825
+ tagScope(opt_attributes.collect((cc) => cc.tags.attribute || [])).ctag(
2826
+ "fn_attributes"
2827
+ ),
2690
2828
  text("fn"),
2691
2829
  req(fnNameDecl, "invalid fn, expected function name"),
2692
2830
  seq(
2693
- req(fnParamList, "invalid fn, expected function parameters").collect(scopeCollect, "header_scope"),
2694
- opt(seq(
2695
- "->",
2696
- opt_attributes.collect((cc) => cc.tags.attribute, "return_attributes"),
2697
- type_specifier.ctag("return_type").collect(scopeCollect, "return_scope")
2698
- )),
2699
- req(
2700
- unscoped_compound_statement,
2701
- "invalid fn, expected function body"
2702
- ).ctag("body_statement").collect(scopeCollect, "body_scope")
2831
+ req(fnParamList, "invalid fn, expected function parameters").collect(
2832
+ scopeCollect,
2833
+ "header_scope"
2834
+ ),
2835
+ opt(
2836
+ seq(
2837
+ "->",
2838
+ opt_attributes.collect((cc) => cc.tags.attribute, "return_attributes"),
2839
+ type_specifier.ctag("return_type").collect(scopeCollect, "return_scope")
2840
+ )
2841
+ ),
2842
+ req(unscoped_compound_statement, "invalid fn, expected function body").ctag("body_statement").collect(scopeCollect, "body_scope")
2703
2843
  )
2704
2844
  ).collect(partialScopeCollect, "fn_partial_scope").collect(fnCollect);
2705
2845
  const global_value_decl = or(
@@ -2720,11 +2860,20 @@ const global_value_decl = or(
2720
2860
  ).collect(collectVarLike("const"))
2721
2861
  ).collect(partialScopeCollect);
2722
2862
  const global_alias = seq(
2723
- weslExtension(opt_attributes).collect((cc) => cc.tags.attribute, "attributes"),
2863
+ weslExtension(opt_attributes).collect(
2864
+ (cc) => cc.tags.attribute,
2865
+ "attributes"
2866
+ ),
2724
2867
  "alias",
2725
- req(word, "invalid alias, expected name").collect(globalDeclCollect, "alias_name"),
2868
+ req(word, "invalid alias, expected name").collect(
2869
+ globalDeclCollect,
2870
+ "alias_name"
2871
+ ),
2726
2872
  req("=", "invalid alias, expected '='"),
2727
- req(type_specifier, "invalid alias, expected type").collect(scopeCollect, "alias_scope"),
2873
+ req(type_specifier, "invalid alias, expected type").collect(
2874
+ scopeCollect,
2875
+ "alias_scope"
2876
+ ),
2728
2877
  req(";", "invalid alias, expected ';'")
2729
2878
  ).collect(aliasCollect);
2730
2879
  const const_assert = tagScope(
@@ -2875,176 +3024,6 @@ function makeBinaryExpression([left, operator, right]) {
2875
3024
  right
2876
3025
  };
2877
3026
  }
2878
- /*!
2879
- Copyright (c) 2017-2021 [these people](https://github.com/Rich-Harris/vlq/graphs/contributors)
2880
-
2881
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
2882
-
2883
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
2884
-
2885
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2886
- */
2887
- let integer_to_char = {};
2888
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split("").forEach(function(char, i) {
2889
- integer_to_char[i] = char;
2890
- });
2891
- function encodeVlq(value) {
2892
- if (typeof value === "number") {
2893
- return encode_integer(value);
2894
- }
2895
- let result = "";
2896
- for (let i = 0; i < value.length; i += 1) {
2897
- result += encode_integer(value[i]);
2898
- }
2899
- return result;
2900
- }
2901
- function encode_integer(num) {
2902
- let result = "";
2903
- if (num < 0) {
2904
- num = -num << 1 | 1;
2905
- } else {
2906
- num <<= 1;
2907
- }
2908
- do {
2909
- let clamped = num & 31;
2910
- num >>>= 5;
2911
- if (num > 0) {
2912
- clamped |= 32;
2913
- }
2914
- result += integer_to_char[clamped];
2915
- } while (num > 0);
2916
- return result;
2917
- }
2918
- async function requestWeslDevice(adapter, descriptor) {
2919
- if (!adapter) {
2920
- throw new Error("No GPU adapter");
2921
- }
2922
- return adapter.requestDevice(descriptor).then(makeWeslDevice);
2923
- }
2924
- function makeWeslDevice(device) {
2925
- const errorScopeStack = [];
2926
- device.injectError = (type, error) => {
2927
- const errorScope = errorScopeStack.findLast((v) => v.filter === type);
2928
- if (errorScope !== void 0) {
2929
- errorScope.errors.push(error);
2930
- } else {
2931
- error.then((e) => {
2932
- if (e !== null) {
2933
- dispatchError(e);
2934
- }
2935
- });
2936
- }
2937
- };
2938
- function dispatchError(e) {
2939
- device.addEventListener(
2940
- "uncapturederror",
2941
- (ev) => {
2942
- if (!ev.defaultPrevented) {
2943
- if ("compilationInfo" in ev.error) {
2944
- const error = ev.error;
2945
- if (error.compilationInfo) {
2946
- for (const message of error.compilationInfo.messages) {
2947
- throwClickableError({
2948
- url: message.module.url,
2949
- text: message.module.text ?? null,
2950
- lineNumber: message.lineNum,
2951
- lineColumn: message.linePos,
2952
- length: message.length,
2953
- error: new Error(message.type + ": " + message.message)
2954
- });
2955
- }
2956
- } else {
2957
- console.error(ev.error.message);
2958
- }
2959
- } else {
2960
- console.error(ev.error.message);
2961
- }
2962
- }
2963
- },
2964
- {
2965
- // This event listener should only happen for this event!
2966
- once: true
2967
- }
2968
- );
2969
- device.dispatchEvent(
2970
- new GPUUncapturedErrorEvent("uncapturederror", { error: e })
2971
- );
2972
- }
2973
- device.pushErrorScope = /* @__PURE__ */ ((baseFn) => {
2974
- return function(filter) {
2975
- errorScopeStack.push({
2976
- filter,
2977
- errors: []
2978
- });
2979
- return baseFn.call(this, filter);
2980
- };
2981
- })(device.pushErrorScope);
2982
- device.popErrorScope = /* @__PURE__ */ ((baseFn) => {
2983
- return function() {
2984
- const errorScope = errorScopeStack.pop();
2985
- if (errorScope === void 0) {
2986
- throw new DOMException(
2987
- "popErrorScope called on empty error scope stack",
2988
- "OperationError"
2989
- );
2990
- }
2991
- errorScope.errors.push(baseFn.call(this));
2992
- const errorPromise = Promise.all(errorScope.errors).then(
2993
- (values) => values.find((v) => v !== null) ?? null
2994
- );
2995
- return errorPromise;
2996
- };
2997
- })(device.popErrorScope);
2998
- return device;
2999
- }
3000
- function throwClickableError({
3001
- url,
3002
- text: text2,
3003
- lineNumber,
3004
- lineColumn,
3005
- length,
3006
- error
3007
- }) {
3008
- let mappings = encodeVlq([
3009
- 0,
3010
- 0,
3011
- Math.max(0, lineNumber - 1),
3012
- Math.max(0, lineColumn - 1)
3013
- ]) + "," + // Sadly no browser makes use of this info to map the error properly
3014
- encodeVlq([
3015
- 18,
3016
- // Arbitrary number that is high enough
3017
- 0,
3018
- Math.max(0, lineNumber - 1),
3019
- Math.max(0, lineColumn - 1) + length
3020
- ]);
3021
- const sourceMap = {
3022
- version: 3,
3023
- file: null,
3024
- sources: [url],
3025
- sourcesContent: [text2 ?? null],
3026
- names: [],
3027
- mappings
3028
- };
3029
- let generatedCode = `throw new Error(${JSON.stringify(error.message + "")})`;
3030
- generatedCode += "\n//# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
3031
- generatedCode += "\n//# sourceURL=" + sourceMap.sources[0];
3032
- let oldLimit = 0;
3033
- if ("stackTraceLimit" in Error) {
3034
- oldLimit = Error.stackTraceLimit;
3035
- Error.stackTraceLimit = 1;
3036
- }
3037
- try {
3038
- (0, eval)(generatedCode);
3039
- } catch (e) {
3040
- if ("stackTraceLimit" in Error) {
3041
- Error.stackTraceLimit = oldLimit;
3042
- }
3043
- error.message = "";
3044
- e.cause = error;
3045
- throw e;
3046
- }
3047
- }
3048
3027
  class WeslParseError extends Error {
3049
3028
  constructor(opts) {
3050
3029
  const source = opts.src.src;
@@ -3219,6 +3198,26 @@ function bindIdents(params) {
3219
3198
  const newStatements = [...globalStatements.values()];
3220
3199
  return { decls, globalNames, newStatements, unbound };
3221
3200
  }
3201
+ function findUnboundIdents(registry) {
3202
+ const bindContext = {
3203
+ registry,
3204
+ conditions: {},
3205
+ knownDecls: /* @__PURE__ */ new Set(),
3206
+ foundScopes: /* @__PURE__ */ new Set(),
3207
+ globalNames: /* @__PURE__ */ new Set(),
3208
+ globalStatements: /* @__PURE__ */ new Map(),
3209
+ mangler: minimalMangle,
3210
+ unbound: [],
3211
+ dontFollowDecls: true
3212
+ };
3213
+ Object.entries(registry.modules).map(([module, ast]) => {
3214
+ const rootDecls = findValidRootDecls(ast.rootScope, {});
3215
+ const declEntries = rootDecls.map((d) => [d.originalName, d]);
3216
+ const liveDecls = { decls: new Map(declEntries), parent: null };
3217
+ bindIdentsRecursive(ast.rootScope, bindContext, liveDecls, true);
3218
+ });
3219
+ return bindContext.unbound;
3220
+ }
3222
3221
  function findValidRootDecls(rootScope, conditions) {
3223
3222
  const found = [];
3224
3223
  for (const e of rootScope.contents) {
@@ -3234,7 +3233,7 @@ function findValidRootDecls(rootScope, conditions) {
3234
3233
  return found;
3235
3234
  }
3236
3235
  function bindIdentsRecursive(scope, bindContext, liveDecls, isRoot = false) {
3237
- const { conditions, foundScopes } = bindContext;
3236
+ const { dontFollowDecls, foundScopes } = bindContext;
3238
3237
  if (foundScopes.has(scope)) return [];
3239
3238
  foundScopes.add(scope);
3240
3239
  const newGlobals = [];
@@ -3254,7 +3253,12 @@ function bindIdentsRecursive(scope, bindContext, liveDecls, isRoot = false) {
3254
3253
  }
3255
3254
  }
3256
3255
  });
3257
- const newFromRefs = newGlobals.flatMap((decl) => {
3256
+ const newFromRefs = dontFollowDecls ? [] : handleDecls(newGlobals, bindContext);
3257
+ return [newGlobals, newFromChildren, newFromRefs].flat();
3258
+ }
3259
+ function handleDecls(newGlobals, bindContext) {
3260
+ const { conditions } = bindContext;
3261
+ return newGlobals.flatMap((decl) => {
3258
3262
  const foundsScope = decl.dependentScope;
3259
3263
  if (foundsScope) {
3260
3264
  const rootDecls = globalDeclToRootLiveDecls(decl, conditions);
@@ -3265,7 +3269,6 @@ function bindIdentsRecursive(scope, bindContext, liveDecls, isRoot = false) {
3265
3269
  }
3266
3270
  return [];
3267
3271
  });
3268
- return [newGlobals, newFromChildren, newFromRefs].flat();
3269
3272
  }
3270
3273
  function handleRef(ident2, liveDecls, bindContext) {
3271
3274
  const { registry, conditions, unbound } = bindContext;
@@ -3278,7 +3281,7 @@ function handleRef(ident2, liveDecls, bindContext) {
3278
3281
  } else if (stdWgsl(ident2.originalName)) {
3279
3282
  ident2.std = true;
3280
3283
  } else if (!unbound) {
3281
- failMissingIdent(ident2);
3284
+ failIdent(ident2, `unresolved identifier '${ident2.originalName}'`);
3282
3285
  }
3283
3286
  }
3284
3287
  }
@@ -3325,16 +3328,6 @@ function globalDeclToRootLiveDecls(decl, conditions) {
3325
3328
  root._scopeDecls = liveDecls;
3326
3329
  return liveDecls;
3327
3330
  }
3328
- function failMissingIdent(ident2) {
3329
- const { refIdentElem } = ident2;
3330
- if (refIdentElem) {
3331
- const { srcModule, start, end } = refIdentElem;
3332
- const { debugFilePath: filePath } = srcModule;
3333
- const msg = `unresolved identifier '${ident2.originalName}' in file: ${filePath}`;
3334
- srcLog(srcModule.src, [start, end], msg);
3335
- throw new Error(msg);
3336
- }
3337
- }
3338
3331
  function setMangledName(proposedName, decl, globalNames, srcModule, mangler) {
3339
3332
  if (!decl.mangledName) {
3340
3333
  let mangledName;
@@ -3380,8 +3373,8 @@ function findQualifiedImport(refIdent2, parsed, conditions, virtuals, unbound) {
3380
3373
  if (unbound) {
3381
3374
  unbound.push(modulePathParts);
3382
3375
  } else {
3383
- const msg = `ident ${modulePathParts.join("::")}, but module not found`;
3384
- console.log(msg);
3376
+ const msg = `module not found for '${modulePathParts.join("::")}'`;
3377
+ failIdent(refIdent2, msg);
3385
3378
  }
3386
3379
  }
3387
3380
  return result;
@@ -3457,16 +3450,21 @@ function lowerAndEmitElem(e, ctx) {
3457
3450
  return;
3458
3451
  // terminal elements copy strings to the output
3459
3452
  case "text":
3460
- return emitText(e, ctx);
3453
+ emitText(e, ctx);
3454
+ return;
3461
3455
  case "name":
3462
- return emitName(e, ctx);
3456
+ emitName(e, ctx);
3457
+ return;
3463
3458
  case "synthetic":
3464
- return emitSynthetic(e, ctx);
3459
+ emitSynthetic(e, ctx);
3460
+ return;
3465
3461
  // identifiers are copied to the output, but with potentially mangled names
3466
3462
  case "ref":
3467
- return emitRefIdent(e, ctx);
3463
+ emitRefIdent(e, ctx);
3464
+ return;
3468
3465
  case "decl":
3469
- return emitDeclIdent(e, ctx);
3466
+ emitDeclIdent(e, ctx);
3467
+ return;
3470
3468
  // container elements just emit their child elements
3471
3469
  case "param":
3472
3470
  case "var":
@@ -3480,7 +3478,8 @@ function lowerAndEmitElem(e, ctx) {
3480
3478
  case "statement":
3481
3479
  case "stuff":
3482
3480
  case "switch-clause":
3483
- return emitContents(e, ctx);
3481
+ emitContents(e, ctx);
3482
+ return;
3484
3483
  // root level container elements get some extra newlines to make the output prettier
3485
3484
  case "override":
3486
3485
  case "const":
@@ -3488,17 +3487,22 @@ function lowerAndEmitElem(e, ctx) {
3488
3487
  case "alias":
3489
3488
  case "gvar":
3490
3489
  emitRootElemNl(ctx);
3491
- return emitContents(e, ctx);
3490
+ emitContents(e, ctx);
3491
+ return;
3492
3492
  case "fn":
3493
3493
  emitRootElemNl(ctx);
3494
- return emitFn(e, ctx);
3494
+ emitFn(e, ctx);
3495
+ return;
3495
3496
  case "struct":
3496
3497
  emitRootElemNl(ctx);
3497
- return emitStruct(e, ctx);
3498
+ emitStruct(e, ctx);
3499
+ return;
3498
3500
  case "attribute":
3499
- return emitAttribute(e, ctx);
3501
+ emitAttribute(e, ctx);
3502
+ return;
3500
3503
  case "directive":
3501
- return emitDirective(e, ctx);
3504
+ emitDirective(e, ctx);
3505
+ return;
3502
3506
  default:
3503
3507
  assertUnreachable(e);
3504
3508
  }
@@ -3547,7 +3551,9 @@ function emitAttributes(attributes, ctx) {
3547
3551
  function emitStruct(e, ctx) {
3548
3552
  const { name: name2, members, start, end } = e;
3549
3553
  const { srcBuilder } = ctx;
3550
- const validMembers = members.filter((m) => conditionsValid(m, ctx.conditions));
3554
+ const validMembers = members.filter(
3555
+ (m) => conditionsValid(m, ctx.conditions)
3556
+ );
3551
3557
  const validLength = validMembers.length;
3552
3558
  if (validLength === 0) {
3553
3559
  warnEmptyStruct(e);
@@ -3573,12 +3579,8 @@ function emitStruct(e, ctx) {
3573
3579
  function warnEmptyStruct(e) {
3574
3580
  const { name: name2, members } = e;
3575
3581
  const condStr = members.length ? "(with current conditions)" : "";
3576
- const { debugFilePath: filePath } = name2.srcModule;
3577
- srcLog(
3578
- name2.srcModule.src,
3579
- e.start,
3580
- `struct ${name2.ident.originalName} in ${filePath} has no members ${condStr}`
3581
- );
3582
+ const message = `struct '${name2.ident.originalName}' has no members ${condStr}`;
3583
+ failIdentElem(name2, message);
3582
3584
  }
3583
3585
  function emitSynthetic(e, ctx) {
3584
3586
  const { text: text2 } = e;
@@ -4015,7 +4017,7 @@ class LinkedWesl {
4015
4017
  code: this.dest
4016
4018
  });
4017
4019
  device.popErrorScope();
4018
- let { promise, resolve } = Promise.withResolvers();
4020
+ const { promise, resolve } = Promise.withResolvers();
4019
4021
  device.injectError("validation", promise);
4020
4022
  module.getCompilationInfo().then((compilationInfo) => {
4021
4023
  if (compilationInfo.messages.length === 0) {
@@ -4059,7 +4061,7 @@ class LinkedWesl {
4059
4061
  const srcPosition = srcMap.destToSrc(message.offset);
4060
4062
  const srcEndPosition = message.length > 0 ? srcMap.destToSrc(message.offset + message.length) : srcPosition;
4061
4063
  const length = srcEndPosition.position - srcPosition.position;
4062
- let [lineNum, linePos] = offsetToLineNumber(
4064
+ const [lineNum, linePos] = offsetToLineNumber(
4063
4065
  srcPosition.position,
4064
4066
  srcPosition.src.text
4065
4067
  );
@@ -4082,7 +4084,7 @@ function compilationInfoToErrorMessage(compilationInfo, shaderModule) {
4082
4084
  if (compilationInfo.messages.length === 0) return null;
4083
4085
  let result = `Compilation log for [Invalid ShaderModule (${shaderModule.label || "unlabled"})]:
4084
4086
  `;
4085
- let errorCount = compilationInfo.messages.filter(
4087
+ const errorCount = compilationInfo.messages.filter(
4086
4088
  (v) => v.type === "error"
4087
4089
  ).length;
4088
4090
  if (errorCount > 0) {
@@ -4190,7 +4192,8 @@ async function link(params) {
4190
4192
  const registry = parsedRegistry();
4191
4193
  parseIntoRegistry(weslSrc, registry, "package", debugWeslRoot);
4192
4194
  parseLibsIntoRegistry(libs, registry);
4193
- return new LinkedWesl(linkRegistry({ registry, ...params }));
4195
+ const srcMap = linkRegistry({ registry, ...params });
4196
+ return new LinkedWesl(srcMap);
4194
4197
  }
4195
4198
  function linkRegistry(params) {
4196
4199
  const bound = bindAndTransform(params);
@@ -4214,7 +4217,7 @@ function bindAndTransform(params) {
4214
4217
  if (constants) {
4215
4218
  virtualLibs = { ...virtualLibs, constants: constantsGenerator(constants) };
4216
4219
  }
4217
- let virtuals = virtualLibs && mapValues(virtualLibs, (fn2) => ({ fn: fn2 }));
4220
+ const virtuals = virtualLibs && mapValues(virtualLibs, (fn2) => ({ fn: fn2 }));
4218
4221
  const bindParams = { rootAst, registry, conditions, virtuals, mangler };
4219
4222
  const bindResults = bindIdents(bindParams);
4220
4223
  const { globalNames, decls: newDecls, newStatements } = bindResults;
@@ -4358,7 +4361,9 @@ function lowerBindingStructs(ast) {
4358
4361
  ({ memberRef, struct }) => transformBindingReference(memberRef, struct)
4359
4362
  );
4360
4363
  bindingRefs.forEach(
4361
- ({ intermediates }) => intermediates.forEach((e) => e.contents = [])
4364
+ ({ intermediates }) => intermediates.forEach((e) => {
4365
+ e.contents = [];
4366
+ })
4362
4367
  );
4363
4368
  const contents = removeBindingStructs(moduleElem);
4364
4369
  moduleElem.contents = [...newVars, ...contents];
@@ -4395,7 +4400,9 @@ function removeBindingStructs(moduleElem) {
4395
4400
  function markBindingStructs(moduleElem) {
4396
4401
  const structs = moduleElem.contents.filter((elem) => elem.kind === "struct");
4397
4402
  const bindingStructs = structs.filter(containsBinding);
4398
- bindingStructs.forEach((struct) => struct.bindingStruct = true);
4403
+ bindingStructs.forEach((struct) => {
4404
+ struct.bindingStruct = true;
4405
+ });
4399
4406
  return bindingStructs;
4400
4407
  }
4401
4408
  function containsBinding(struct) {
@@ -4469,17 +4476,18 @@ function findRefsToBindingStructs(moduleElem) {
4469
4476
  }
4470
4477
  function refersToBindingStruct(memberRef) {
4471
4478
  const found = traceToStruct(memberRef.name.ident);
4472
- if (found && found.struct.bindingStruct) {
4479
+ if (found == null ? void 0 : found.struct.bindingStruct) {
4473
4480
  return { memberRef, ...found };
4474
4481
  }
4475
4482
  }
4476
4483
  function traceToStruct(ident2) {
4484
+ var _a;
4477
4485
  const decl = findDecl(ident2);
4478
4486
  const declElem = decl.declElem;
4479
4487
  if (declElem && declElem.kind === "param") {
4480
- const name2 = declElem.name.typeRef.name;
4488
+ const name2 = (_a = declElem.name.typeRef) == null ? void 0 : _a.name;
4481
4489
  if (typeof name2 !== "string") {
4482
- if (name2.std) {
4490
+ if (name2 == null ? void 0 : name2.std) {
4483
4491
  return void 0;
4484
4492
  }
4485
4493
  const paramDecl = findDecl(name2);
@@ -4504,6 +4512,88 @@ function transformBindingReference(memberRef, struct) {
4504
4512
  memberRef.contents = [synthElem];
4505
4513
  return synthElem;
4506
4514
  }
4515
+ async function requestWeslDevice(adapter, descriptor) {
4516
+ if (!adapter) {
4517
+ throw new Error("No GPU adapter");
4518
+ }
4519
+ return adapter.requestDevice(descriptor).then(makeWeslDevice);
4520
+ }
4521
+ function makeWeslDevice(device) {
4522
+ const errorScopeStack = [];
4523
+ device.injectError = (type, error) => {
4524
+ const errorScope = errorScopeStack.findLast((v) => v.filter === type);
4525
+ if (errorScope !== void 0) {
4526
+ errorScope.errors.push(error);
4527
+ } else {
4528
+ error.then((e) => {
4529
+ if (e !== null) {
4530
+ dispatchError(e);
4531
+ }
4532
+ });
4533
+ }
4534
+ };
4535
+ function dispatchError(e) {
4536
+ device.addEventListener(
4537
+ "uncapturederror",
4538
+ (ev) => {
4539
+ if (!ev.defaultPrevented) {
4540
+ if ("compilationInfo" in ev.error) {
4541
+ const error = ev.error;
4542
+ if (error.compilationInfo) {
4543
+ for (const message of error.compilationInfo.messages) {
4544
+ throwClickableError({
4545
+ url: message.module.url,
4546
+ text: message.module.text ?? null,
4547
+ lineNumber: message.lineNum,
4548
+ lineColumn: message.linePos,
4549
+ length: message.length,
4550
+ error: new Error(message.type + ": " + message.message)
4551
+ });
4552
+ }
4553
+ } else {
4554
+ console.error(ev.error.message);
4555
+ }
4556
+ } else {
4557
+ console.error(ev.error.message);
4558
+ }
4559
+ }
4560
+ },
4561
+ {
4562
+ // This event listener should only happen for this event!
4563
+ once: true
4564
+ }
4565
+ );
4566
+ device.dispatchEvent(
4567
+ new GPUUncapturedErrorEvent("uncapturederror", { error: e })
4568
+ );
4569
+ }
4570
+ device.pushErrorScope = /* @__PURE__ */ ((baseFn) => {
4571
+ return function(filter) {
4572
+ errorScopeStack.push({
4573
+ filter,
4574
+ errors: []
4575
+ });
4576
+ return baseFn.call(this, filter);
4577
+ };
4578
+ })(device.pushErrorScope);
4579
+ device.popErrorScope = /* @__PURE__ */ ((baseFn) => {
4580
+ return function() {
4581
+ const errorScope = errorScopeStack.pop();
4582
+ if (errorScope === void 0) {
4583
+ throw new DOMException(
4584
+ "popErrorScope called on empty error scope stack",
4585
+ "OperationError"
4586
+ );
4587
+ }
4588
+ errorScope.errors.push(baseFn.call(this));
4589
+ const errorPromise = Promise.all(errorScope.errors).then(
4590
+ (values) => values.find((v) => v !== null) ?? null
4591
+ );
4592
+ return errorPromise;
4593
+ };
4594
+ })(device.popErrorScope);
4595
+ return device;
4596
+ }
4507
4597
  export {
4508
4598
  LinkedWesl,
4509
4599
  WeslParseError,
@@ -4511,6 +4601,7 @@ export {
4511
4601
  astToString,
4512
4602
  attributeToString$1 as attributeToString,
4513
4603
  bindAndTransform,
4604
+ bindIdents,
4514
4605
  bindingStructsPlugin,
4515
4606
  blankWeslParseState,
4516
4607
  childIdent,
@@ -4522,10 +4613,13 @@ export {
4522
4613
  filterMap,
4523
4614
  findMap,
4524
4615
  findRefsToBindingStructs,
4616
+ findUnboundIdents,
4617
+ findValidRootDecls,
4525
4618
  flatImports,
4526
4619
  groupBy,
4527
4620
  grouped,
4528
4621
  identToString,
4622
+ isGlobal,
4529
4623
  last,
4530
4624
  lengthPrefixMangle,
4531
4625
  link,
@@ -4560,7 +4654,6 @@ export {
4560
4654
  scopeToStringLong,
4561
4655
  selectModule,
4562
4656
  syntheticWeslParseState,
4563
- throwClickableError,
4564
4657
  transformBindingReference,
4565
4658
  transformBindingStruct,
4566
4659
  underscoreMangle