wesl 0.7.22 → 0.7.24

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.
package/dist/index.js CHANGED
@@ -85,7 +85,6 @@ function getStarts(src) {
85
85
  startCache.set(src, starts);
86
86
  return starts;
87
87
  }
88
-
89
88
  //#endregion
90
89
  //#region src/Assertions.ts
91
90
  /** checks whether a condition is true, otherwise throws */
@@ -94,7 +93,7 @@ function assertThat(condition, msg) {
94
93
  }
95
94
  /** when debug is enabled, checks whether a condition is true, otherwise throws */
96
95
  function assertThatDebug(condition, msg) {
97
- if (debug) assertThat(condition, msg);
96
+ assertThat(condition, msg);
98
97
  }
99
98
  /**
100
99
  * Useful to validate that all cases are handled,
@@ -112,7 +111,6 @@ var ErrorWithData = class extends Error {
112
111
  this.data = options?.data;
113
112
  }
114
113
  };
115
-
116
114
  //#endregion
117
115
  //#region src/Util.ts
118
116
  function multiKeySet(m, a, b, v) {
@@ -243,7 +241,6 @@ function errorHighlight(source, span) {
243
241
  const linePos = Math.max(0, span[0] - lineStartOffset);
244
242
  return [source.slice(lineStartOffset, lineEndOffset), " ".repeat(linePos) + "^".repeat(caretCount)];
245
243
  }
246
-
247
244
  //#endregion
248
245
  //#region src/vlq/vlq.ts
249
246
  /*!
@@ -280,7 +277,6 @@ function encode_integer(num) {
280
277
  } while (enc > 0);
281
278
  return result;
282
279
  }
283
-
284
280
  //#endregion
285
281
  //#region src/ClickableError.ts
286
282
  const isBrowser = "document" in globalThis;
@@ -295,7 +291,7 @@ function throwClickableError(params) {
295
291
  length
296
292
  };
297
293
  error.weslLocation = weslLocation;
298
- if (!debug || !isBrowser) throw error;
294
+ if (!isBrowser) throw error;
299
295
  const mappings = encodeVlq([
300
296
  0,
301
297
  0,
@@ -328,7 +324,7 @@ function throwClickableError(params) {
328
324
  } catch (e) {
329
325
  if ("stackTraceLimit" in Error) Error.stackTraceLimit = oldLimit;
330
326
  error.message = "";
331
- if (debug) e.cause = error;
327
+ e.cause = error;
332
328
  e.weslLocation = weslLocation;
333
329
  throw e;
334
330
  }
@@ -356,7 +352,6 @@ function failIdentElem(identElem, msg = "") {
356
352
  error: new Error(detailedMessage)
357
353
  });
358
354
  }
359
-
360
355
  //#endregion
361
356
  //#region src/Conditions.ts
362
357
  /** @return true if the @if attribute is valid with current Conditions */
@@ -453,7 +448,6 @@ function findConditional(attributes) {
453
448
  if (kind === "@if" || kind === "@elif" || kind === "@else") return attr.attribute;
454
449
  }
455
450
  }
456
-
457
451
  //#endregion
458
452
  //#region src/Scope.ts
459
453
  /** Combine two scope siblings.
@@ -502,13 +496,79 @@ function childScope(child) {
502
496
  function childIdent(child) {
503
497
  return !childScope(child);
504
498
  }
505
-
506
499
  //#endregion
507
- //#region src/LowerAndEmit.ts
508
- /** Valid WGSL standard attributes (from spec). Non-WGSL attributes are stripped.
509
- * See: https://www.w3.org/TR/WGSL/#attributes
510
- * Note: @builtin, @diagnostic, @interpolate are parsed as separate attribute types. */
511
- const wgslStandardAttributes$1 = new Set([
500
+ //#region src/StandardTypes.ts
501
+ const stdFns = `bitcast all any select arrayLength
502
+ abs acos acosh asin asinh atan atanh atan2 ceil clamp cos cosh
503
+ countLeadingZeros countOneBits countTrailingZeros cross
504
+ degrees determinant distance dot dot4U8Packed dot4I8Packed
505
+ exp exp2 extractBits faceForward firstLeadingBit firstTrailingBit
506
+ floor fma fract frexp insertBits inverseSqrt ldexp length log log2
507
+ max min mix modf normalize pow quantizeToF16 radians reflect refract
508
+ reverseBits round saturate sign sin sinh smoothstep sqrt step tan tanh
509
+ transpose trunc
510
+ dpdx dpdxCoarse dpdxFine dpdy dpdyCoarse dpdyFine fwidth
511
+ fwidthCoarse fwidthFine
512
+ textureDimensions textureGather textureGatherCompare textureLoad
513
+ textureNumLayers textureNumLevels textureNumSamples
514
+ textureSample textureSampleBias textureSampleCompare textureSampleCompareLevel
515
+ textureSampleGrad textureSampleLevel textureSampleBaseClampToEdge
516
+ textureStore
517
+ atomicLoad atomicStore atomicAdd atomicSub atomicMax atomicMin
518
+ atomicAnd atomicOr atomicXor atomicExchange atomicCompareExchangeWeak
519
+ pack4x8snorm pack4x8unorm pack4xI8 pack4xU8 pack4xI8Clamp pack4xU8Clamp
520
+ pack2x16snorm pack2x16unorm pack2x16float
521
+ unpack4x8snorm unpack4x8unorm unpack4xI8 unpack4xU8
522
+ unpack2x16snorm unpack2x16unorm unpack2x16float
523
+ storageBarrier textureBarrier workgroupBarrier workgroupUniformLoad
524
+ subgroupAdd subgroupAll subgroupAnd subgroupAny subgroupBallot
525
+ subgroupBroadcast subgroupBroadcastFirst subgroupElect
526
+ subgroupExclusiveAdd subgroupExclusiveMul subgroupInclusiveAdd
527
+ subgroupInclusiveMul subgroupMax subgroupMin subgroupMul subgroupOr
528
+ subgroupShuffle subgroupShuffleUp subgroupShuffleXor subgroupXor
529
+ quadBroadcast quadSwapDiagonal quadSwapX quadSwapY`.split(/\s+/);
530
+ const sampledTextureTypes = `
531
+ texture_1d texture_2d texture_2d_array texture_3d
532
+ texture_cube texture_cube_array
533
+ `;
534
+ const multisampledTextureTypes = `
535
+ texture_multisampled_2d texture_depth_multisampled_2d
536
+ `;
537
+ const textureStorageTypes = `
538
+ texture_storage_1d texture_storage_2d texture_storage_2d_array
539
+ texture_storage_3d
540
+ `;
541
+ const stdTypes = `array atomic bool f16 f32 i32
542
+ mat2x2 mat2x3 mat2x4 mat3x2 mat3x3 mat3x4 mat4x2 mat4x3 mat4x4
543
+ mat2x2f mat2x3f mat2x4f mat3x2f mat3x3f mat3x4f
544
+ mat4x2f mat4x3f mat4x4f
545
+ mat2x2h mat2x3h mat2x4h mat3x2h mat3x3h mat3x4h
546
+ mat4x2h mat4x3h mat4x4h
547
+ u32 vec2 vec3 vec4 ptr
548
+ vec2i vec3i vec4i vec2u vec3u vec4u
549
+ vec2f vec3f vec4f vec2h vec3h vec4h
550
+ ${sampledTextureTypes}
551
+ ${multisampledTextureTypes}
552
+ texture_external
553
+ ${textureStorageTypes}
554
+ texture_depth_2d texture_depth_2d_array texture_depth_cube
555
+ texture_depth_cube_array
556
+ sampler sampler_comparison
557
+ rgba8unorm rgba8snorm rgba8uint rgba8sint
558
+ rgba16uint rgba16sint rgba16float
559
+ r32uint r32sint r32float rg32uint rg32sint rg32float
560
+ rgba32uint rgba32sint rgba32float
561
+ bgra8unorm`.split(/\s+/);
562
+ /** https://www.w3.org/TR/WGSL/#predeclared-enumerants */
563
+ const stdEnumerants = `read write read_write
564
+ function private workgroup uniform storage
565
+ rgba8unorm rgba8snorm rgba8uint rgba8sint
566
+ rgba16uint rgba16sint rgba16float
567
+ r32uint r32sint r32float rg32uint rg32sint rg32float
568
+ rgba32uint rgba32sint rgba32float bgra8unorm`.split(/\s+/);
569
+ /** WGSL standard attributes whose params need binding (e.g., @workgroup_size).
570
+ * See: https://www.w3.org/TR/WGSL/#attributes */
571
+ const wgslStandardAttributes = new Set([
512
572
  "align",
513
573
  "binding",
514
574
  "blend_src",
@@ -524,6 +584,20 @@ const wgslStandardAttributes$1 = new Set([
524
584
  "vertex",
525
585
  "workgroup_size"
526
586
  ]);
587
+ /** return true if the name is for a built in type (not a user struct) */
588
+ function stdType(name) {
589
+ return stdTypes.includes(name);
590
+ }
591
+ /** return true if the name is for a built in fn (not a user function) */
592
+ function stdFn(name) {
593
+ return stdFns.includes(name) || stdType(name);
594
+ }
595
+ /** return true if the name is for a built in enumerant */
596
+ function stdEnumerant(name) {
597
+ return stdEnumerants.includes(name);
598
+ }
599
+ //#endregion
600
+ //#region src/LowerAndEmit.ts
527
601
  /** Traverse the AST, starting from root elements, emitting WGSL for each. */
528
602
  function lowerAndEmit(params) {
529
603
  const { srcBuilder, rootElems, conditions } = params;
@@ -803,7 +877,7 @@ function emitAttribute(e, ctx) {
803
877
  const { kind } = e.attribute;
804
878
  if (kind === "@if" || kind === "@elif" || kind === "@else") return false;
805
879
  if (kind === "@attribute") {
806
- if (!wgslStandardAttributes$1.has(e.attribute.name)) return false;
880
+ if (!wgslStandardAttributes.has(e.attribute.name)) return false;
807
881
  emitStandardAttribute(e, ctx);
808
882
  return true;
809
883
  }
@@ -893,7 +967,6 @@ function findDecl(ident) {
893
967
  } while (i);
894
968
  throw new Error(`unresolved identifer: ${ident.originalName}`);
895
969
  }
896
-
897
970
  //#endregion
898
971
  //#region src/debug/ImportToString.ts
899
972
  function importToString(tree) {
@@ -909,7 +982,6 @@ function segmentToString(segment) {
909
982
  } else if (segment.kind === "import-collection") return `{${segment.subtrees.map((s) => importToStringImpl(s)).join(", ")}}`;
910
983
  else assertUnreachable(segment);
911
984
  }
912
-
913
985
  //#endregion
914
986
  //#region src/debug/LineWrapper.ts
915
987
  /** debug utility for constructing strings that wrap at a fixed column width
@@ -970,7 +1042,6 @@ function firstLineLength(s) {
970
1042
  const i = s.indexOf("\n");
971
1043
  return i === -1 ? s.length : i;
972
1044
  }
973
-
974
1045
  //#endregion
975
1046
  //#region src/debug/ASTtoString.ts
976
1047
  const maxLineLength = 150;
@@ -1111,7 +1182,6 @@ function debugContentsToString(elem) {
1111
1182
  return `?${c.kind}?`;
1112
1183
  }).join(" ");
1113
1184
  }
1114
-
1115
1185
  //#endregion
1116
1186
  //#region src/debug/ScopeToString.ts
1117
1187
  /** A debugging print of the scope tree with identifiers in nested brackets */
@@ -1168,7 +1238,6 @@ function identToString(ident) {
1168
1238
  return `%${originalName}${mangledName ? `(${mangledName})` : ""} ${idStr} `;
1169
1239
  }
1170
1240
  }
1171
-
1172
1241
  //#endregion
1173
1242
  //#region src/LiveDeclarations.ts
1174
1243
  /** create a LiveDecls */
@@ -1183,7 +1252,6 @@ function liveDeclsToString(liveDecls) {
1183
1252
  const { decls, parent } = liveDecls;
1184
1253
  return `decls: { ${Array.from(decls.entries()).map(([name, decl]) => `${name}:${identToString(decl)}`).join(", ")} }, parent: ${parent ? liveDeclsToString(parent) : "null"}`;
1185
1254
  }
1186
-
1187
1255
  //#endregion
1188
1256
  //#region src/Mangler.ts
1189
1257
  /**
@@ -1225,7 +1293,6 @@ function minimallyMangledName(proposedName, globalNames) {
1225
1293
  while (globalNames.has(renamed)) renamed = proposedName + conflicts++;
1226
1294
  return renamed;
1227
1295
  }
1228
-
1229
1296
  //#endregion
1230
1297
  //#region src/ModulePathUtil.ts
1231
1298
  /** WESL module path utilities for converting between :: and / separators. */
@@ -1262,7 +1329,6 @@ function normalizeDebugRoot(root) {
1262
1329
  if (root === "") return "";
1263
1330
  return root.endsWith("/") ? root : root + "/";
1264
1331
  }
1265
-
1266
1332
  //#endregion
1267
1333
  //#region src/FlattenTreeImport.ts
1268
1334
  /**
@@ -1287,7 +1353,6 @@ function flattenTreeImport(imp) {
1287
1353
  else assertUnreachable(finalSegment);
1288
1354
  }
1289
1355
  }
1290
-
1291
1356
  //#endregion
1292
1357
  //#region src/ParseError.ts
1293
1358
  var ParseError = class extends Error {
@@ -1297,7 +1362,6 @@ var ParseError = class extends Error {
1297
1362
  this.span = span;
1298
1363
  }
1299
1364
  };
1300
-
1301
1365
  //#endregion
1302
1366
  //#region src/parse/ContentsHelpers.ts
1303
1367
  /** Push partial element onto stack for content collection. */
@@ -1347,7 +1411,6 @@ function coverWithText(ctx, contents, start, end) {
1347
1411
  if (pos < end) elems.push(makeText(srcModule, pos, end));
1348
1412
  return elems;
1349
1413
  }
1350
-
1351
1414
  //#endregion
1352
1415
  //#region src/parse/ExpressionUtil.ts
1353
1416
  function makeLiteral(token) {
@@ -1420,7 +1483,6 @@ function makeCallExpression(fn, templateArgs, args, end) {
1420
1483
  end
1421
1484
  };
1422
1485
  }
1423
-
1424
1486
  //#endregion
1425
1487
  //#region src/parse/ParseUtil.ts
1426
1488
  /** Match text and throw ParseError if not found. */
@@ -1521,7 +1583,6 @@ function linkDeclIdentElem(declIdentElem, declElem) {
1521
1583
  function linkDeclIdent(typedDecl, declElem) {
1522
1584
  linkDeclIdentElem(typedDecl.decl, declElem);
1523
1585
  }
1524
-
1525
1586
  //#endregion
1526
1587
  //#region src/parse/OperatorBinding.ts
1527
1588
  /**
@@ -1592,7 +1653,6 @@ function getOpGroup(op) {
1592
1653
  }
1593
1654
  /** Validate WGSL 8.19 operator binding restrictions, return op's group. */
1594
1655
  function checkOpBinding(stream, op, leftGroup) {
1595
- if (!validation) return leftGroup;
1596
1656
  const opGroup = getOpGroup(op);
1597
1657
  if (!canBindLeft(op, leftGroup)) throwParseError(stream, `'${op}' requires parentheses after ${leftGroup}`);
1598
1658
  if (!canSelfChain(opGroup) && leftGroup === opGroup) throwParseError(stream, `'${op}' cannot be chained`);
@@ -1616,7 +1676,6 @@ function canSelfChain(group) {
1616
1676
  function isBitwise(g) {
1617
1677
  return g === "bitAnd" || g === "bitXor" || g === "bitOr";
1618
1678
  }
1619
-
1620
1679
  //#endregion
1621
1680
  //#region src/parse/ParseIdent.ts
1622
1681
  /** WESL keywords that cannot be used as path segment identifiers. */
@@ -1671,7 +1730,6 @@ function isPathSegment(token, isFirst) {
1671
1730
  if (weslKeywords.has(token.text)) return isFirst && pathPrefixKeywords.has(token.text);
1672
1731
  return true;
1673
1732
  }
1674
-
1675
1733
  //#endregion
1676
1734
  //#region src/parse/ParseType.ts
1677
1735
  /**
@@ -1714,7 +1772,6 @@ function parseTemplateParam(ctx) {
1714
1772
  if (expr) return expr;
1715
1773
  throwParseError(ctx.stream, "Expected expression in template parameters");
1716
1774
  }
1717
-
1718
1775
  //#endregion
1719
1776
  //#region src/parse/ParseCall.ts
1720
1777
  /**
@@ -1756,7 +1813,6 @@ function matchCloseParen(stream) {
1756
1813
  const token = stream.matchText(")");
1757
1814
  return token ? token.span[1] : null;
1758
1815
  }
1759
-
1760
1816
  //#endregion
1761
1817
  //#region src/parse/ParseExpression.ts
1762
1818
  /**
@@ -1920,7 +1976,6 @@ function parseIndexAccess(ctx, base) {
1920
1976
  if (!stream.matchText("[")) return null;
1921
1977
  return makeComponentExpression(base, expectExpression(ctx, "Expected expression in array index"), expect(stream, "]", "array index").span[1]);
1922
1978
  }
1923
-
1924
1979
  //#endregion
1925
1980
  //#region src/parse/ParseAttribute.ts
1926
1981
  /** Grammar: attribute * */
@@ -2108,7 +2163,6 @@ function parseAttrParam(ctx) {
2108
2163
  contents: finishContents(ctx, start, end)
2109
2164
  };
2110
2165
  }
2111
-
2112
2166
  //#endregion
2113
2167
  //#region src/parse/ParseDirective.ts
2114
2168
  /** Grammar: global_directive : diagnostic_directive | enable_directive | requires_directive */
@@ -2169,7 +2223,6 @@ function makeDirectiveElem(directive, token, stream, attributes) {
2169
2223
  attachAttributes(elem, attributes);
2170
2224
  return elem;
2171
2225
  }
2172
-
2173
2226
  //#endregion
2174
2227
  //#region src/parse/ParseControlFlow.ts
2175
2228
  /**
@@ -2252,7 +2305,6 @@ function parseCaseBody(ctx, errorMsg) {
2252
2305
  if (!body) throwParseError(ctx.stream, errorMsg);
2253
2306
  ctx.addElem(body);
2254
2307
  }
2255
-
2256
2308
  //#endregion
2257
2309
  //#region src/parse/ParseValueDeclaration.ts
2258
2310
  /** Grammar: 'const' optionally_typed_ident '=' expression (global or local) */
@@ -2335,7 +2387,6 @@ function parseOptionalType(ctx) {
2335
2387
  typeScope
2336
2388
  };
2337
2389
  }
2338
-
2339
2390
  //#endregion
2340
2391
  //#region src/parse/ParseGlobalVar.ts
2341
2392
  /**
@@ -2414,7 +2465,6 @@ function skipTemplateList(ctx) {
2414
2465
  stream.nextToken();
2415
2466
  }
2416
2467
  }
2417
-
2418
2468
  //#endregion
2419
2469
  //#region src/parse/ParseLocalVar.ts
2420
2470
  /**
@@ -2449,7 +2499,6 @@ function parseVarOrLet(ctx, keyword, hasTemplate, requiresInit, attributes) {
2449
2499
  linkDeclIdent(typedDecl, elem);
2450
2500
  return elem;
2451
2501
  }
2452
-
2453
2502
  //#endregion
2454
2503
  //#region src/parse/ParseSimpleStatement.ts
2455
2504
  const assignmentOps = new Set([
@@ -2559,7 +2608,6 @@ function parseAssignmentRhs(ctx) {
2559
2608
  function parseIncDecOperator(stream) {
2560
2609
  return !!stream.nextIf(({ text }) => text === "++" || text === "--");
2561
2610
  }
2562
-
2563
2611
  //#endregion
2564
2612
  //#region src/parse/ParseLoop.ts
2565
2613
  /**
@@ -2628,7 +2676,6 @@ function parseForUpdate(ctx) {
2628
2676
  if (expr && ctx.options.preserveExpressions) ctx.addElem(expr);
2629
2677
  parseIncDecOperator(ctx.stream) || parseAssignmentRhs(ctx);
2630
2678
  }
2631
-
2632
2679
  //#endregion
2633
2680
  //#region src/parse/ParseStatement.ts
2634
2681
  /** Function bodies share scope with parameters (per WGSL spec). */
@@ -2738,7 +2785,6 @@ function finalizeConditional$1(ctx, hasConditional, attributes) {
2738
2785
  function getConditionalAttribute(attributes) {
2739
2786
  return attributes.find((a) => isConditionalAttribute$1(a.attribute))?.attribute;
2740
2787
  }
2741
-
2742
2788
  //#endregion
2743
2789
  //#region src/parse/ParseFn.ts
2744
2790
  /**
@@ -2835,7 +2881,6 @@ function parseFnParam(ctx) {
2835
2881
  attachAttributes(elem, attributes.length > 0 ? attributes : void 0);
2836
2882
  return elem;
2837
2883
  }
2838
-
2839
2884
  //#endregion
2840
2885
  //#region src/parse/ParseImport.ts
2841
2886
  /** WESL Grammar: translation_unit : import_statement* global_directive* global_decl* */
@@ -2961,7 +3006,6 @@ function makeImportItem(name, as) {
2961
3006
  as
2962
3007
  };
2963
3008
  }
2964
-
2965
3009
  //#endregion
2966
3010
  //#region src/parse/ParseStruct.ts
2967
3011
  /**
@@ -3022,7 +3066,6 @@ function parseStructMember(ctx) {
3022
3066
  attachAttributes(elem, attributes.length ? attributes : void 0);
3023
3067
  return elem;
3024
3068
  }
3025
-
3026
3069
  //#endregion
3027
3070
  //#region src/parse/ParseModule.ts
3028
3071
  const declParsers = [
@@ -3094,7 +3137,6 @@ function recordDecl(ctx, elem, attrs) {
3094
3137
  function isConditionalAttribute(a) {
3095
3138
  return a.kind === "@if" || a.kind === "@elif" || a.kind === "@else";
3096
3139
  }
3097
-
3098
3140
  //#endregion
3099
3141
  //#region src/parse/ParsingContext.ts
3100
3142
  /** Context for parsers to build AST and manage scopes. */
@@ -3166,7 +3208,6 @@ var ParsingContext = class {
3166
3208
  this.state.context.scope.contents.push(ident);
3167
3209
  }
3168
3210
  };
3169
-
3170
3211
  //#endregion
3171
3212
  //#region src/parse/Keywords.ts
3172
3213
  /** https://www.w3.org/TR/WGSL/#keyword-summary */
@@ -3187,7 +3228,6 @@ const reservedWords = `NULL Self abstract active alignas alignof as asm asm_frag
3187
3228
  self set shared sizeof smooth snorm static static_assert static_cast std subroutine super
3188
3229
  target template this thread_local throw trait try type typedef typeid typename typeof
3189
3230
  union unless unorm unsafe unsized use using varying virtual volatile wgsl where with writeonly yield`.split(/\s+/);
3190
-
3191
3231
  //#endregion
3192
3232
  //#region src/parse/stream/CachingStream.ts
3193
3233
  var CachingStream = class {
@@ -3237,7 +3277,6 @@ var Cache = class extends Map {
3237
3277
  return super.set(k, v);
3238
3278
  }
3239
3279
  };
3240
-
3241
3280
  //#endregion
3242
3281
  //#region src/parse/stream/RegexHelpers.ts
3243
3282
  function toRegexSource(nameExp) {
@@ -3267,7 +3306,6 @@ function matchOneOf(syms) {
3267
3306
  const escaped = syms.split(/\s+/).sort((a, b) => b.length - a.length).filter((s) => s).map(escapeRegex);
3268
3307
  return new RegExp(escaped.join("|"));
3269
3308
  }
3270
-
3271
3309
  //#endregion
3272
3310
  //#region src/parse/stream/MatchersStream.ts
3273
3311
  /** Runs a `RegexMatchers` on an input string */
@@ -3330,7 +3368,6 @@ function findGroupDex(indices) {
3330
3368
  };
3331
3369
  }
3332
3370
  }
3333
-
3334
3371
  //#endregion
3335
3372
  //#region src/parse/WeslStream.ts
3336
3373
  /** Whitespaces including new lines */
@@ -3514,7 +3551,6 @@ var WeslStream = class {
3514
3551
  }
3515
3552
  }
3516
3553
  };
3517
-
3518
3554
  //#endregion
3519
3555
  //#region src/parse/ParseWesl.ts
3520
3556
  /** Parse a WESL source module into an AST. */
@@ -3564,7 +3600,6 @@ function createParseState(srcModule, options) {
3564
3600
  state
3565
3601
  };
3566
3602
  }
3567
-
3568
3603
  //#endregion
3569
3604
  //#region src/ParseWESL.ts
3570
3605
  /** Human-readable error when parsing WESL fails. */
@@ -3594,116 +3629,16 @@ function flatImports(ast, conditions) {
3594
3629
  if (!conditions) ast._flatImports = flat;
3595
3630
  return flat;
3596
3631
  }
3597
-
3598
- //#endregion
3599
- //#region src/StandardTypes.ts
3600
- const stdFns = `bitcast all any select arrayLength
3601
- abs acos acosh asin asinh atan atanh atan2 ceil clamp cos cosh
3602
- countLeadingZeros countOneBits countTrailingZeros cross
3603
- degrees determinant distance dot dot4U8Packed dot4I8Packed
3604
- exp exp2 extractBits faceForward firstLeadingBit firstTrailingBit
3605
- floor fma fract frexp insertBits inverseSqrt ldexp length log log2
3606
- max min mix modf normalize pow quantizeToF16 radians reflect refract
3607
- reverseBits round saturate sign sin sinh smoothstep sqrt step tan tanh
3608
- transpose trunc
3609
- dpdx dpdxCoarse dpdxFine dpdy dpdyCoarse dpdyFine fwidth
3610
- fwidthCoarse fwidthFine
3611
- textureDimensions textureGather textureGatherCompare textureLoad
3612
- textureNumLayers textureNumLevels textureNumSamples
3613
- textureSample textureSampleBias textureSampleCompare textureSampleCompareLevel
3614
- textureSampleGrad textureSampleLevel textureSampleBaseClampToEdge
3615
- textureStore
3616
- atomicLoad atomicStore atomicAdd atomicSub atomicMax atomicMin
3617
- atomicAnd atomicOr atomicXor atomicExchange atomicCompareExchangeWeak
3618
- pack4x8snorm pack4x8unorm pack4xI8 pack4xU8 pack4xI8Clamp pack4xU8Clamp
3619
- pack2x16snorm pack2x16unorm pack2x16float
3620
- unpack4x8snorm unpack4x8unorm unpack4xI8 unpack4xU8
3621
- unpack2x16snorm unpack2x16unorm unpack2x16float
3622
- storageBarrier textureBarrier workgroupBarrier workgroupUniformLoad
3623
- subgroupAdd subgroupAll subgroupAnd subgroupAny subgroupBallot
3624
- subgroupBroadcast subgroupBroadcastFirst subgroupElect
3625
- subgroupExclusiveAdd subgroupExclusiveMul subgroupInclusiveAdd
3626
- subgroupInclusiveMul subgroupMax subgroupMin subgroupMul subgroupOr
3627
- subgroupShuffle subgroupShuffleUp subgroupShuffleXor subgroupXor
3628
- quadBroadcast quadSwapDiagonal quadSwapX quadSwapY`.split(/\s+/);
3629
- const sampledTextureTypes = `
3630
- texture_1d texture_2d texture_2d_array texture_3d
3631
- texture_cube texture_cube_array
3632
- `;
3633
- const multisampledTextureTypes = `
3634
- texture_multisampled_2d texture_depth_multisampled_2d
3635
- `;
3636
- const textureStorageTypes = `
3637
- texture_storage_1d texture_storage_2d texture_storage_2d_array
3638
- texture_storage_3d
3639
- `;
3640
- const stdTypes = `array atomic bool f16 f32 i32
3641
- mat2x2 mat2x3 mat2x4 mat3x2 mat3x3 mat3x4 mat4x2 mat4x3 mat4x4
3642
- mat2x2f mat2x3f mat2x4f mat3x2f mat3x3f mat3x4f
3643
- mat4x2f mat4x3f mat4x4f
3644
- mat2x2h mat2x3h mat2x4h mat3x2h mat3x3h mat3x4h
3645
- mat4x2h mat4x3h mat4x4h
3646
- u32 vec2 vec3 vec4 ptr
3647
- vec2i vec3i vec4i vec2u vec3u vec4u
3648
- vec2f vec3f vec4f vec2h vec3h vec4h
3649
- ${sampledTextureTypes}
3650
- ${multisampledTextureTypes}
3651
- texture_external
3652
- ${textureStorageTypes}
3653
- texture_depth_2d texture_depth_2d_array texture_depth_cube
3654
- texture_depth_cube_array
3655
- sampler sampler_comparison
3656
- rgba8unorm rgba8snorm rgba8uint rgba8sint
3657
- rgba16uint rgba16sint rgba16float
3658
- r32uint r32sint r32float rg32uint rg32sint rg32float
3659
- rgba32uint rgba32sint rgba32float
3660
- bgra8unorm`.split(/\s+/);
3661
- /** https://www.w3.org/TR/WGSL/#predeclared-enumerants */
3662
- const stdEnumerants = `read write read_write
3663
- function private workgroup uniform storage
3664
- rgba8unorm rgba8snorm rgba8uint rgba8sint
3665
- rgba16uint rgba16sint rgba16float
3666
- r32uint r32sint r32float rg32uint rg32sint rg32float
3667
- rgba32uint rgba32sint rgba32float bgra8unorm`.split(/\s+/);
3668
- /** return true if the name is for a built in type (not a user struct) */
3669
- function stdType(name) {
3670
- return stdTypes.includes(name);
3671
- }
3672
- /** return true if the name is for a built in fn (not a user function) */
3673
- function stdFn(name) {
3674
- return stdFns.includes(name) || stdType(name);
3675
- }
3676
- /** return true if the name is for a built in enumerant */
3677
- function stdEnumerant(name) {
3678
- return stdEnumerants.includes(name);
3679
- }
3680
-
3681
3632
  //#endregion
3682
3633
  //#region src/BindIdents.ts
3683
- /** WGSL standard attributes whose params need binding (e.g., @workgroup_size). */
3684
- const wgslStandardAttributes = new Set([
3685
- "align",
3686
- "binding",
3687
- "blend_src",
3688
- "compute",
3689
- "const",
3690
- "fragment",
3691
- "group",
3692
- "id",
3693
- "invariant",
3694
- "location",
3695
- "must_use",
3696
- "size",
3697
- "vertex",
3698
- "workgroup_size"
3699
- ]);
3700
3634
  /** Bind ref idents to declarations and mangle global declaration names. */
3701
3635
  function bindIdents(params) {
3702
3636
  const { rootAst, resolver, virtuals, accumulateUnbound } = params;
3703
3637
  const { conditions = {}, mangler = minimalMangle } = params;
3638
+ const { discoveryMode } = params;
3704
3639
  const packageName = rootAst.srcModule.modulePath.split("::")[0];
3705
- const validRootDecls = findValidRootDecls(rootAst.rootScope, conditions);
3706
- const { globalNames, knownDecls } = initRootDecls(validRootDecls);
3640
+ const rootDecls = discoveryMode ? findAllRootDecls(rootAst.rootScope) : findValidRootDecls(rootAst.rootScope, conditions);
3641
+ const { globalNames, knownDecls } = initRootDecls(rootDecls);
3707
3642
  const bindContext = {
3708
3643
  resolver,
3709
3644
  conditions,
@@ -3714,13 +3649,14 @@ function bindIdents(params) {
3714
3649
  foundScopes: /* @__PURE__ */ new Set(),
3715
3650
  globalNames,
3716
3651
  globalStatements: /* @__PURE__ */ new Map(),
3717
- unbound: accumulateUnbound ? [] : void 0
3652
+ unbound: accumulateUnbound ? [] : void 0,
3653
+ discoveryMode
3718
3654
  };
3719
3655
  const liveDecls = {
3720
- decls: new Map(validRootDecls.map((d) => [d.originalName, d])),
3656
+ decls: new Map(rootDecls.map((d) => [d.originalName, d])),
3721
3657
  parent: null
3722
3658
  };
3723
- const fromRootDecls = validRootDecls.flatMap((decl) => processDependentScope(decl, bindContext));
3659
+ const fromRootDecls = rootDecls.flatMap((decl) => processDependentScope(decl, bindContext));
3724
3660
  const fromRefs = bindIdentsRecursive(rootAst.rootScope, bindContext, liveDecls);
3725
3661
  const newStatements = [...bindContext.globalStatements.values()];
3726
3662
  return {
@@ -3756,17 +3692,11 @@ function* validItems(scope, conditions) {
3756
3692
  }
3757
3693
  /** Find all conditionally valid declarations at the root level. */
3758
3694
  function findValidRootDecls(rootScope, conditions) {
3759
- const found = [];
3760
- for (const item of validItems(rootScope, conditions)) if (item.kind === "decl") found.push(item);
3761
- else if (item.kind === "partial") collectDecls(item, found);
3762
- return found;
3695
+ return collectDecls(validItems(rootScope, conditions));
3763
3696
  }
3764
3697
  /** Find all declarations at the root level, ignoring conditions. */
3765
3698
  function findAllRootDecls(rootScope) {
3766
- const found = [];
3767
- for (const item of rootScope.contents) if (item.kind === "decl") found.push(item);
3768
- else if (item.kind === "partial") collectDecls(item, found);
3769
- return found;
3699
+ return collectDecls(rootScope.contents);
3770
3700
  }
3771
3701
  /** Find a public declaration with the given original name. */
3772
3702
  function publicDecl(scope, name, conditions) {
@@ -3834,10 +3764,11 @@ function handleRef(ident, liveDecls, bindContext) {
3834
3764
  }
3835
3765
  if (!bindContext.unbound) failIdent(ident, `unresolved identifier '${ident.originalName}'`);
3836
3766
  }
3767
+ /** Follow new global declarations into their dependent scopes. */
3837
3768
  function handleDecls(newGlobals, bindContext) {
3838
3769
  return newGlobals.flatMap((decl) => processDependentScope(decl, bindContext));
3839
3770
  }
3840
- /** If found declaration is new, mangle its name. Return if it's a global declaration. */
3771
+ /** If found declaration is new, mangle its name. @return the decl if it's global. */
3841
3772
  function handleNewDecl(refIdent, foundDecl, ctx) {
3842
3773
  const { decl, moduleAst } = foundDecl;
3843
3774
  const { knownDecls, globalNames, mangler, globalStatements } = ctx;
@@ -3864,7 +3795,8 @@ function findDeclInModule(ident, liveDecls) {
3864
3795
  /** Match a ref ident to a declaration in another module via import or qualified ident. */
3865
3796
  function findQualifiedImport(refIdent, ctx) {
3866
3797
  const { conditions, unbound, discoveryMode } = ctx;
3867
- const flatImps = flatImports(refIdent.ast, discoveryMode ? void 0 : conditions);
3798
+ const conds = discoveryMode ? void 0 : conditions;
3799
+ const flatImps = flatImports(refIdent.ast, conds);
3868
3800
  const identParts = refIdent.originalName.split("::");
3869
3801
  const pathParts = matchingImport(identParts, flatImps) ?? qualifiedIdent(identParts);
3870
3802
  if (!pathParts) {
@@ -3918,7 +3850,7 @@ function virtualModule(moduleName, ctx) {
3918
3850
  /** Get cached valid root declarations, computing on first access. */
3919
3851
  function getValidRootDecls(rootScope, conditions) {
3920
3852
  const lexScope = rootScope;
3921
- if (!lexScope._validRootDecls) lexScope._validRootDecls = findValidRootDecls(rootScope, conditions);
3853
+ lexScope._validRootDecls ??= findValidRootDecls(rootScope, conditions);
3922
3854
  return lexScope._validRootDecls;
3923
3855
  }
3924
3856
  /** Given a global declIdent, return the liveDecls for its root scope. */
@@ -3947,29 +3879,198 @@ function setMangledName(proposedName, decl, globalNames, srcModule, mangler) {
3947
3879
  function stdWgsl(name) {
3948
3880
  return stdType(name) || stdFn(name) || stdEnumerant(name);
3949
3881
  }
3882
+ /** @return identParts if it's a qualified path (has ::). */
3950
3883
  function qualifiedIdent(identParts) {
3951
3884
  if (identParts.length > 1) return identParts;
3952
3885
  }
3953
- /** Collect all declarations in a scope (used when scope is already validated). */
3954
- function collectDecls(scope, found) {
3955
- for (const item of scope.contents) if (item.kind === "decl") found.push(item);
3956
- else if (item.kind === "partial") collectDecls(item, found);
3886
+ /** Collect all declarations from scope items, recursing into partial scopes. */
3887
+ function collectDecls(items) {
3888
+ return [...items].flatMap((item) => {
3889
+ const { kind } = item;
3890
+ if (kind === "decl") return [item];
3891
+ if (kind === "partial") return collectDecls(item.contents);
3892
+ return [];
3893
+ });
3957
3894
  }
3958
-
3959
3895
  //#endregion
3960
- //#region src/discovery/FindUnboundIdents.ts
3961
- /**
3962
- * Find unbound package references in library sources.
3963
- *
3964
- * Binds local references without following cross-package imports, revealing
3965
- * which external packages are referenced but not resolved.
3966
- *
3967
- * @param resolver - Module resolver that supports batch operations
3968
- * @returns Array of unbound module paths, each as an array of path segments
3969
- * (e.g., [['foo', 'bar', 'baz'], ['other', 'pkg']])
3970
- */
3971
- function findUnboundIdents(resolver) {
3972
- return findUnboundRefs(resolver).map((ref) => ref.path);
3896
+ //#region src/PathUtil.ts
3897
+ /** simplistic path manipulation utilities */
3898
+ /** return path with ./ and foo/.. elements removed */
3899
+ function normalize(path) {
3900
+ const noDots = path.split("/").filter((s) => s !== ".");
3901
+ const noDbl = [];
3902
+ noDots.forEach((s) => {
3903
+ if (s !== "") if (s === ".." && noDbl.length && noDbl[noDbl.length - 1] !== "..") noDbl.pop();
3904
+ else noDbl.push(s);
3905
+ });
3906
+ return noDbl.join("/");
3907
+ }
3908
+ /** return path w/o a suffix.
3909
+ * e.g. /foo/bar.wgsl => /foo/bar */
3910
+ function noSuffix(path) {
3911
+ const lastSlash = path.lastIndexOf("/");
3912
+ const lastStart = lastSlash === -1 ? 0 : lastSlash + 1;
3913
+ const suffix = path.indexOf(".", lastStart);
3914
+ const suffixStart = suffix === -1 ? path.length : suffix;
3915
+ return path.slice(0, suffixStart);
3916
+ }
3917
+ //#endregion
3918
+ //#region src/ModuleResolver.ts
3919
+ const libRegex = /^lib\.w[eg]sl$/i;
3920
+ /** Module resolver for in-memory source records. Lazy by default. */
3921
+ var RecordResolver = class {
3922
+ astCache = /* @__PURE__ */ new Map();
3923
+ sources;
3924
+ packageName;
3925
+ debugWeslRoot;
3926
+ constructor(sources, options = {}) {
3927
+ const { packageName = "package", debugWeslRoot } = options;
3928
+ this.sources = sources;
3929
+ this.packageName = packageName;
3930
+ this.debugWeslRoot = normalizeDebugRoot(debugWeslRoot);
3931
+ }
3932
+ resolveModule(modulePath) {
3933
+ const cached = this.astCache.get(modulePath);
3934
+ if (cached) return cached;
3935
+ const source = this.findSource(modulePath);
3936
+ if (source === void 0) return void 0;
3937
+ const ast = parseSrcModule({
3938
+ modulePath,
3939
+ debugFilePath: this.modulePathToDebugPath(modulePath),
3940
+ src: source
3941
+ });
3942
+ this.astCache.set(modulePath, ast);
3943
+ return ast;
3944
+ }
3945
+ findSource(modulePath) {
3946
+ if (this.sources[modulePath] !== void 0) return this.sources[modulePath];
3947
+ const filePath = this.moduleToFilePath(modulePath);
3948
+ if (filePath === void 0) return void 0;
3949
+ return findInVariants(this.sources, filePath);
3950
+ }
3951
+ /** Convert module path to file path, or undefined if not local. */
3952
+ moduleToFilePath(modulePath) {
3953
+ return moduleToRelativePath(modulePath, this.packageName);
3954
+ }
3955
+ modulePathToDebugPath(modulePath) {
3956
+ const filePath = this.moduleToFilePath(modulePath) ?? modulePath;
3957
+ return this.debugWeslRoot + filePath + ".wesl";
3958
+ }
3959
+ /** Parse all modules and return entries. */
3960
+ allModules() {
3961
+ for (const filePath of Object.keys(this.sources)) {
3962
+ const treatLibAsRoot = this.packageName !== "package";
3963
+ const modulePath = fileToModulePath(filePath, this.packageName, treatLibAsRoot);
3964
+ this.resolveModule(modulePath);
3965
+ }
3966
+ return this.astCache.entries();
3967
+ }
3968
+ };
3969
+ /** Composite resolver that tries each resolver in order until one succeeds. */
3970
+ var CompositeResolver = class {
3971
+ resolvers;
3972
+ constructor(resolvers) {
3973
+ this.resolvers = resolvers;
3974
+ }
3975
+ resolveModule(modulePath) {
3976
+ for (const resolver of this.resolvers) {
3977
+ const ast = resolver.resolveModule(modulePath);
3978
+ if (ast) return ast;
3979
+ }
3980
+ }
3981
+ };
3982
+ /** Lazy resolver for WeslBundle library modules. */
3983
+ var BundleResolver = class {
3984
+ astCache = /* @__PURE__ */ new Map();
3985
+ sources;
3986
+ packageName;
3987
+ debugWeslRoot;
3988
+ constructor(bundle, debugWeslRoot) {
3989
+ this.sources = bundle.modules;
3990
+ this.packageName = bundle.name;
3991
+ this.debugWeslRoot = normalizeDebugRoot(debugWeslRoot);
3992
+ }
3993
+ resolveModule(modulePath) {
3994
+ const pkgPrefix = this.packageName + "::";
3995
+ if (modulePath !== this.packageName && !modulePath.startsWith(pkgPrefix)) return;
3996
+ const cached = this.astCache.get(modulePath);
3997
+ if (cached) return cached;
3998
+ const source = this.findSource(modulePath);
3999
+ if (!source) return void 0;
4000
+ const ast = parseSrcModule({
4001
+ modulePath,
4002
+ debugFilePath: this.modulePathToDebugPath(modulePath),
4003
+ src: source
4004
+ });
4005
+ this.astCache.set(modulePath, ast);
4006
+ return ast;
4007
+ }
4008
+ findSource(modulePath) {
4009
+ const filePath = this.moduleToFilePath(modulePath);
4010
+ if (modulePath === this.packageName) {
4011
+ const libSrc = findInVariants(this.sources, "lib", ["wesl", "wgsl"]);
4012
+ if (libSrc) return libSrc;
4013
+ }
4014
+ return findInVariants(this.sources, filePath);
4015
+ }
4016
+ moduleToFilePath(modulePath) {
4017
+ return moduleToRelativePath(modulePath, this.packageName) ?? modulePath;
4018
+ }
4019
+ modulePathToDebugPath(modulePath) {
4020
+ const filePath = this.moduleToFilePath(modulePath);
4021
+ return this.debugWeslRoot + this.packageName + "/" + filePath + ".wesl";
4022
+ }
4023
+ };
4024
+ /** Wrap a resolver so each resolveModule call returns a freshly parsed AST.
4025
+ * Use this when reusing a resolver across multiple link() calls, since binding
4026
+ * mutates ASTs in place. Each wrapper instance caches within itself, so within
4027
+ * a single link pass the same module path returns the same AST object.
4028
+ * Re-parsing is faster than structuredClone due to cycle-tracking overhead
4029
+ * from Scope.parent backpointers. */
4030
+ function freshResolver(inner) {
4031
+ const cache = /* @__PURE__ */ new Map();
4032
+ return { resolveModule(modulePath) {
4033
+ const cached = cache.get(modulePath);
4034
+ if (cached) return cached;
4035
+ const ast = inner.resolveModule(modulePath);
4036
+ if (!ast) return void 0;
4037
+ const fresh = parseSrcModule(ast.srcModule);
4038
+ cache.set(modulePath, fresh);
4039
+ return fresh;
4040
+ } };
4041
+ }
4042
+ /** Convert file path to module path (e.g., "foo/bar.wesl" to "package::foo::bar"). */
4043
+ function fileToModulePath(filePath, packageName, treatLibAsRoot) {
4044
+ if (filePath.includes("::")) return filePath;
4045
+ if (treatLibAsRoot && libRegex.test(filePath)) return packageName;
4046
+ const moduleSuffix = noSuffix(normalize(filePath)).replaceAll("/", "::");
4047
+ return packageName + "::" + moduleSuffix;
4048
+ }
4049
+ /** Try path variants with/without ./ prefix and extension suffixes. */
4050
+ function findInVariants(sources, basePath, extensions = ["wesl", "wgsl"]) {
4051
+ for (const prefix of ["", "./"]) {
4052
+ const path = prefix + basePath;
4053
+ if (sources[path] !== void 0) return sources[path];
4054
+ for (const ext of extensions) {
4055
+ const withExt = `${path}.${ext}`;
4056
+ if (sources[withExt] !== void 0) return sources[withExt];
4057
+ }
4058
+ }
4059
+ }
4060
+ //#endregion
4061
+ //#region src/discovery/FindUnboundIdents.ts
4062
+ /**
4063
+ * Find unbound package references in library sources.
4064
+ *
4065
+ * Binds local references without following cross-package imports, revealing
4066
+ * which external packages are referenced but not resolved.
4067
+ *
4068
+ * @param resolver - Module resolver that supports batch operations
4069
+ * @returns Array of unbound module paths, each as an array of path segments
4070
+ * (e.g., [['foo', 'bar', 'baz'], ['other', 'pkg']])
4071
+ */
4072
+ function findUnboundIdents(resolver) {
4073
+ return findUnboundRefs(resolver).map((ref) => ref.path);
3973
4074
  }
3974
4075
  /** Find unbound references with full position info. */
3975
4076
  function findUnboundRefs(resolver) {
@@ -3992,14 +4093,48 @@ function findUnboundRefs(resolver) {
3992
4093
  decls: new Map(rootDecls.map((d) => [d.originalName, d])),
3993
4094
  parent: null
3994
4095
  };
3995
- filterMap(rootDecls, (decl) => decl.dependentScope).forEach((s) => {
3996
- bindIdentsRecursive(s, bindContext, makeLiveDecls(liveDecls));
3997
- });
4096
+ for (const s of filterMap(rootDecls, (decl) => decl.dependentScope)) bindIdentsRecursive(s, bindContext, makeLiveDecls(liveDecls));
3998
4097
  bindIdentsRecursive(ast.rootScope, bindContext, liveDecls);
3999
4098
  }
4000
4099
  return bindContext.unbound;
4001
4100
  }
4002
-
4101
+ /** Thin decorator that records which modules were resolved. */
4102
+ var TrackingResolver = class {
4103
+ visited = /* @__PURE__ */ new Set();
4104
+ #inner;
4105
+ constructor(inner) {
4106
+ this.#inner = inner;
4107
+ }
4108
+ resolveModule(modulePath) {
4109
+ const ast = this.#inner.resolveModule(modulePath);
4110
+ if (ast) this.visited.add(modulePath);
4111
+ return ast;
4112
+ }
4113
+ };
4114
+ /**
4115
+ * Discover reachable modules and unbound external refs from a single root.
4116
+ *
4117
+ * Traces the import graph from `rootModuleName`, returning only the reachable
4118
+ * local modules in `weslSrc` and unresolved external references in `unbound`.
4119
+ */
4120
+ function discoverModules(weslSrc, resolver, rootModuleName, packageName = "package") {
4121
+ const tracking = new TrackingResolver(resolver);
4122
+ const rootAst = tracking.resolveModule(rootModuleName);
4123
+ if (!rootAst) throw new Error(`root module not found: '${rootModuleName}'`);
4124
+ const result = bindIdents({
4125
+ rootAst,
4126
+ resolver: tracking,
4127
+ accumulateUnbound: true,
4128
+ discoveryMode: true
4129
+ });
4130
+ const moduleToKey = new Map(Object.keys(weslSrc).map((key) => [fileToModulePath(key, packageName, false), key]));
4131
+ const reachable = [...tracking.visited].map((m) => moduleToKey.get(m)).filter((key) => key !== void 0).map((key) => [key, weslSrc[key]]);
4132
+ const unbound = (result.unbound ?? []).map((ref) => ref.path);
4133
+ return {
4134
+ weslSrc: Object.fromEntries(reachable),
4135
+ unbound
4136
+ };
4137
+ }
4003
4138
  //#endregion
4004
4139
  //#region src/discovery/PackageNameUtils.ts
4005
4140
  /** Package name sanitization for WESL.
@@ -4063,7 +4198,6 @@ function breakAt(str, delimiter) {
4063
4198
  if (index === -1) return [str, ""];
4064
4199
  return [str.slice(0, index), str.slice(index)];
4065
4200
  }
4066
-
4067
4201
  //#endregion
4068
4202
  //#region src/LinkedWesl.ts
4069
4203
  /**
@@ -4168,156 +4302,6 @@ function compilationInfoToErrorMessage(compilationInfo, shaderModule) {
4168
4302
  }
4169
4303
  return result;
4170
4304
  }
4171
-
4172
- //#endregion
4173
- //#region src/PathUtil.ts
4174
- /** simplistic path manipulation utilities */
4175
- /** return path with ./ and foo/.. elements removed */
4176
- function normalize(path) {
4177
- const noDots = path.split("/").filter((s) => s !== ".");
4178
- const noDbl = [];
4179
- noDots.forEach((s) => {
4180
- if (s !== "") if (s === ".." && noDbl.length && noDbl[noDbl.length - 1] !== "..") noDbl.pop();
4181
- else noDbl.push(s);
4182
- });
4183
- return noDbl.join("/");
4184
- }
4185
- /** return path w/o a suffix.
4186
- * e.g. /foo/bar.wgsl => /foo/bar */
4187
- function noSuffix(path) {
4188
- const lastSlash = path.lastIndexOf("/");
4189
- const lastStart = lastSlash === -1 ? 0 : lastSlash + 1;
4190
- const suffix = path.indexOf(".", lastStart);
4191
- const suffixStart = suffix === -1 ? path.length : suffix;
4192
- return path.slice(0, suffixStart);
4193
- }
4194
-
4195
- //#endregion
4196
- //#region src/ModuleResolver.ts
4197
- const libRegex = /^lib\.w[eg]sl$/i;
4198
- /** Module resolver for in-memory source records. Lazy by default. */
4199
- var RecordResolver = class {
4200
- astCache = /* @__PURE__ */ new Map();
4201
- sources;
4202
- packageName;
4203
- debugWeslRoot;
4204
- constructor(sources, options = {}) {
4205
- const { packageName = "package", debugWeslRoot } = options;
4206
- this.sources = sources;
4207
- this.packageName = packageName;
4208
- this.debugWeslRoot = normalizeDebugRoot(debugWeslRoot);
4209
- }
4210
- resolveModule(modulePath) {
4211
- const cached = this.astCache.get(modulePath);
4212
- if (cached) return cached;
4213
- const source = this.findSource(modulePath);
4214
- if (source === void 0) return void 0;
4215
- const ast = parseSrcModule({
4216
- modulePath,
4217
- debugFilePath: this.modulePathToDebugPath(modulePath),
4218
- src: source
4219
- });
4220
- this.astCache.set(modulePath, ast);
4221
- return ast;
4222
- }
4223
- findSource(modulePath) {
4224
- if (this.sources[modulePath] !== void 0) return this.sources[modulePath];
4225
- const filePath = this.moduleToFilePath(modulePath);
4226
- if (filePath === void 0) return void 0;
4227
- return findInVariants(this.sources, filePath);
4228
- }
4229
- /** Convert module path to file path, or undefined if not local. */
4230
- moduleToFilePath(modulePath) {
4231
- return moduleToRelativePath(modulePath, this.packageName);
4232
- }
4233
- modulePathToDebugPath(modulePath) {
4234
- const filePath = this.moduleToFilePath(modulePath) ?? modulePath;
4235
- return this.debugWeslRoot + filePath + ".wesl";
4236
- }
4237
- /** Parse all modules and return entries. */
4238
- allModules() {
4239
- for (const filePath of Object.keys(this.sources)) {
4240
- const treatLibAsRoot = this.packageName !== "package";
4241
- const modulePath = fileToModulePath(filePath, this.packageName, treatLibAsRoot);
4242
- this.resolveModule(modulePath);
4243
- }
4244
- return this.astCache.entries();
4245
- }
4246
- };
4247
- /** Composite resolver that tries each resolver in order until one succeeds. */
4248
- var CompositeResolver = class {
4249
- resolvers;
4250
- constructor(resolvers) {
4251
- this.resolvers = resolvers;
4252
- }
4253
- resolveModule(modulePath) {
4254
- for (const resolver of this.resolvers) {
4255
- const ast = resolver.resolveModule(modulePath);
4256
- if (ast) return ast;
4257
- }
4258
- }
4259
- };
4260
- /** Lazy resolver for WeslBundle library modules. */
4261
- var BundleResolver = class {
4262
- astCache = /* @__PURE__ */ new Map();
4263
- sources;
4264
- packageName;
4265
- debugWeslRoot;
4266
- constructor(bundle, debugWeslRoot) {
4267
- this.sources = bundle.modules;
4268
- this.packageName = bundle.name;
4269
- this.debugWeslRoot = normalizeDebugRoot(debugWeslRoot);
4270
- }
4271
- resolveModule(modulePath) {
4272
- const pkgPrefix = this.packageName + "::";
4273
- if (modulePath !== this.packageName && !modulePath.startsWith(pkgPrefix)) return;
4274
- const cached = this.astCache.get(modulePath);
4275
- if (cached) return cached;
4276
- const source = this.findSource(modulePath);
4277
- if (!source) return void 0;
4278
- const ast = parseSrcModule({
4279
- modulePath,
4280
- debugFilePath: this.modulePathToDebugPath(modulePath),
4281
- src: source
4282
- });
4283
- this.astCache.set(modulePath, ast);
4284
- return ast;
4285
- }
4286
- findSource(modulePath) {
4287
- const filePath = this.moduleToFilePath(modulePath);
4288
- if (modulePath === this.packageName) {
4289
- const libSrc = findInVariants(this.sources, "lib", ["wesl", "wgsl"]);
4290
- if (libSrc) return libSrc;
4291
- }
4292
- return findInVariants(this.sources, filePath);
4293
- }
4294
- moduleToFilePath(modulePath) {
4295
- return moduleToRelativePath(modulePath, this.packageName) ?? modulePath;
4296
- }
4297
- modulePathToDebugPath(modulePath) {
4298
- const filePath = this.moduleToFilePath(modulePath);
4299
- return this.debugWeslRoot + this.packageName + "/" + filePath + ".wesl";
4300
- }
4301
- };
4302
- /** Convert file path to module path (e.g., "foo/bar.wesl" to "package::foo::bar"). */
4303
- function fileToModulePath(filePath, packageName, treatLibAsRoot) {
4304
- if (filePath.includes("::")) return filePath;
4305
- if (treatLibAsRoot && libRegex.test(filePath)) return packageName;
4306
- const moduleSuffix = noSuffix(normalize(filePath)).replaceAll("/", "::");
4307
- return packageName + "::" + moduleSuffix;
4308
- }
4309
- /** Try path variants with/without ./ prefix and extension suffixes. */
4310
- function findInVariants(sources, basePath, extensions = ["wesl", "wgsl"]) {
4311
- for (const prefix of ["", "./"]) {
4312
- const path = prefix + basePath;
4313
- if (sources[path] !== void 0) return sources[path];
4314
- for (const ext of extensions) {
4315
- const withExt = `${path}.${ext}`;
4316
- if (sources[withExt] !== void 0) return sources[withExt];
4317
- }
4318
- }
4319
- }
4320
-
4321
4305
  //#endregion
4322
4306
  //#region src/SrcMap.ts
4323
4307
  /** map text ranges in multiple src texts to a single dest text */
@@ -4468,7 +4452,6 @@ var SrcMapBuilder = class {
4468
4452
  return map;
4469
4453
  }
4470
4454
  };
4471
-
4472
4455
  //#endregion
4473
4456
  //#region src/Linker.ts
4474
4457
  /**
@@ -4564,7 +4547,7 @@ function normalizeModuleName(name) {
4564
4547
  function getRootModule(resolver, modulePath, rootModuleName) {
4565
4548
  const rootAst = resolver.resolveModule(modulePath);
4566
4549
  if (!rootAst) {
4567
- if (debug) console.log(`root module not found: ${modulePath} (from ${rootModuleName})`);
4550
+ console.log(`root module not found: ${modulePath} (from ${rootModuleName})`);
4568
4551
  throw new Error(`Root module not found: ${rootModuleName}`);
4569
4552
  }
4570
4553
  return rootAst;
@@ -4640,7 +4623,6 @@ function emitDecl(decl, conditions) {
4640
4623
  });
4641
4624
  return builder;
4642
4625
  }
4643
-
4644
4626
  //#endregion
4645
4627
  //#region src/LinkerUtil.ts
4646
4628
  function visitAst(elem, visitor) {
@@ -4649,7 +4631,6 @@ function visitAst(elem, visitor) {
4649
4631
  visitAst(child, visitor);
4650
4632
  });
4651
4633
  }
4652
-
4653
4634
  //#endregion
4654
4635
  //#region src/RawEmit.ts
4655
4636
  function attributeToString$1(e) {
@@ -4697,13 +4678,11 @@ function contentsToString(elem) {
4697
4678
  else if (elem.kind === "name") return elem.name;
4698
4679
  else assertUnreachable(elem);
4699
4680
  }
4700
-
4701
4681
  //#endregion
4702
4682
  //#region src/Reflection.ts
4703
4683
  const textureStorage = matchOneOf(textureStorageTypes);
4704
- const textureTypes = matchOneOf(sampledTextureTypes);
4705
- const multiNames = matchOneOf(multisampledTextureTypes);
4706
-
4684
+ matchOneOf(sampledTextureTypes);
4685
+ matchOneOf(multisampledTextureTypes);
4707
4686
  //#endregion
4708
4687
  //#region src/TransformBindingStructs.ts
4709
4688
  function bindingStructsPlugin() {
@@ -4887,7 +4866,7 @@ function transformBindingReference(memberRef, struct) {
4887
4866
  const refName = memberRef.member.name;
4888
4867
  const structMember = struct.members.find((m) => m.name.name === refName);
4889
4868
  if (!structMember || !structMember.mangledVarName) {
4890
- if (debug) console.log(`missing mangledVarName for ${refName}`);
4869
+ console.log(`missing mangledVarName for ${refName}`);
4891
4870
  return {
4892
4871
  kind: "synthetic",
4893
4872
  text: refName
@@ -4902,7 +4881,6 @@ function transformBindingReference(memberRef, struct) {
4902
4881
  memberRef.contents = [synthElem];
4903
4882
  return synthElem;
4904
4883
  }
4905
-
4906
4884
  //#endregion
4907
4885
  //#region src/WeslDevice.ts
4908
4886
  /**
@@ -4970,6 +4948,5 @@ function makeWeslDevice(device) {
4970
4948
  })(device.popErrorScope);
4971
4949
  return device;
4972
4950
  }
4973
-
4974
4951
  //#endregion
4975
- export { BundleResolver, CompositeResolver, LinkedWesl, ParseError, RecordResolver, SrcMap, SrcMapBuilder, WeslParseError, WeslStream, _linkSync, astToString, attributeToString, bindAndTransform, bindIdents, bindIdentsRecursive, bindingStructsPlugin, childIdent, childScope, containsScope, debug, debugContentsToString, emptyScope, errorHighlight, fileToModulePath, filterMap, findAllRootDecls, findMap, findRefsToBindingStructs, findUnboundIdents, findUnboundRefs, findValidRootDecls, flatImports, groupBy, grouped, identToString, last, lengthPrefixMangle, link, linkRegistry, liveDeclsToString, log, lowerBindingStructs, makeLiveDecls, makeWeslDevice, mapForward, mapValues, markBindingStructs, markEntryTypes, mergeScope, minimalMangle, minimallyMangledName, modulePartsToRelativePath, moduleToRelativePath, multiKeySet, multisampledTextureTypes, nextIdentId, noSuffix, normalize, normalizeDebugRoot, normalizeModuleName, npmNameVariations, offsetToLineNumber, overlapTail, parseSrcModule, partition, publicDecl, replaceWords, requestWeslDevice, resetScopeIds, resolveModulePath, sampledTextureTypes, sanitizePackageName, scan, scopeToString, scopeToStringLong, srcLog, stdEnumerant, stdEnumerants, stdFn, stdFns, stdType, stdTypes, textureStorageTypes, transformBindingReference, transformBindingStruct, underscoreMangle, validation, withLoggerAsync };
4952
+ export { BundleResolver, CompositeResolver, LinkedWesl, ParseError, RecordResolver, SrcMap, SrcMapBuilder, TrackingResolver, WeslParseError, WeslStream, _linkSync, astToString, attributeToString, bindAndTransform, bindIdents, bindIdentsRecursive, bindingStructsPlugin, childIdent, childScope, containsScope, debug, debugContentsToString, discoverModules, emptyScope, errorHighlight, fileToModulePath, filterMap, filterValidElements, findAllRootDecls, findMap, findRefsToBindingStructs, findUnboundIdents, findUnboundRefs, findValidRootDecls, flatImports, freshResolver, groupBy, grouped, identToString, last, lengthPrefixMangle, link, linkRegistry, liveDeclsToString, log, lowerBindingStructs, makeLiveDecls, makeWeslDevice, mapForward, mapValues, markBindingStructs, markEntryTypes, mergeScope, minimalMangle, minimallyMangledName, modulePartsToRelativePath, moduleToRelativePath, multiKeySet, multisampledTextureTypes, nextIdentId, noSuffix, normalize, normalizeDebugRoot, normalizeModuleName, npmNameVariations, offsetToLineNumber, overlapTail, parseSrcModule, partition, publicDecl, replaceWords, requestWeslDevice, resetScopeIds, resolveModulePath, sampledTextureTypes, sanitizePackageName, scan, scopeToString, scopeToStringLong, srcLog, stdEnumerant, stdEnumerants, stdFn, stdFns, stdType, stdTypes, textureStorageTypes, transformBindingReference, transformBindingStruct, underscoreMangle, validation, wgslStandardAttributes, withLoggerAsync };