wesl 0.6.46 → 0.6.48

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.d.ts CHANGED
@@ -924,6 +924,62 @@ declare function scopeToString(scope: Scope, indent?: number, shortIdents?: bool
924
924
  declare function scopeToStringLong(scope: Scope): string;
925
925
  declare function identToString(ident?: Ident): string;
926
926
  //#endregion
927
+ //#region src/discovery/FindUnboundIdents.d.ts
928
+ /**
929
+ * Find unbound package references in library sources.
930
+ *
931
+ * Binds local references without following cross-package imports, revealing
932
+ * which external packages are referenced but not resolved.
933
+ *
934
+ * @param resolver - Module resolver that supports batch operations
935
+ * @returns Array of unbound module paths, each as an array of path segments
936
+ * (e.g., [['foo', 'bar', 'baz'], ['other', 'pkg']])
937
+ */
938
+ declare function findUnboundIdents(resolver: BatchModuleResolver): string[][];
939
+ //#endregion
940
+ //#region src/discovery/PackageNameUtils.d.ts
941
+ /** Package name sanitization for WESL.
942
+ *
943
+ * Converts typical npm package names to WGSL-safe identifiers using double-underscore encoding.
944
+ * NPM package names can contain `@`, `/`, and `-`, which are not allowed in WGSL identifiers.
945
+ *
946
+ * ## Encoding Scheme
947
+ *
948
+ * ```
949
+ * @ ==> (remove)
950
+ * / ==> __ (double underscore)
951
+ * - ==> _ (single underscore)
952
+ * ```
953
+ *
954
+ * ## Forward Mapping (npm ==> WGSL identifier)
955
+ *
956
+ * ```
957
+ * my_package ==> my_package
958
+ * random-wgsl ==> random_wgsl
959
+ * @scope/my-pkg ==> scope__my_pkg
960
+ * ```
961
+ *
962
+ * ## Reverse Mapping (WGSL identifier ==> npm package)
963
+ *
964
+ * ```
965
+ * scope__my_pkg ==> try: @scope/my_pkg, @scope/my-pkg
966
+ * random_wgsl ==> try: random_wgsl, random-wgsl
967
+ * ```
968
+ */
969
+ /** Convert npm package name to WGSL-safe identifier using double-underscore encoding. */
970
+ declare function sanitizePackageName(npmName: string): string;
971
+ /** Generate npm package name variations from sanitized WESL identifier.
972
+ *
973
+ * Uses double-underscore encoding to distinguish scoped vs unscoped packages:
974
+ * - Has __ → scoped package (try @scope/pkg variants)
975
+ * - No __ → unscoped package (try pkg variants)
976
+ *
977
+ * Examples:
978
+ * "lygia__shader_utils" → ["@lygia/shader_utils", "@lygia/shader-utils"]
979
+ * "random_wgsl" → ["random_wgsl", "random-wgsl"]
980
+ */
981
+ declare function npmNameVariations(sanitizedPath: string): Generator<string>;
982
+ //#endregion
927
983
  //#region src/PathUtil.d.ts
928
984
  /** simplistic path manipulation utilities */
929
985
  /** return path with ./ and foo/.. elements removed */
@@ -1063,4 +1119,4 @@ declare function offsetToLineNumber(offset: number, text: string): [lineNum: num
1063
1119
  */
1064
1120
  declare function errorHighlight(source: string, span: Span): [string, string];
1065
1121
  //#endregion
1066
- export { AbstractElem, AbstractElemBase, AliasElem, Attribute, AttributeElem, BatchModuleResolver, BinaryExpression, BinaryOperator, BindIdentsParams, BindResults, BindingAST, BindingStructElem, BoundAndTransformed, BuiltinAttribute, BundleResolver, ComponentExpression, ComponentMemberExpression, CompositeResolver, Conditions, ConstAssertElem, ConstElem, ContainerElem, DeclIdent, DeclIdentElem, DeclarationElem, DiagnosticAttribute, DiagnosticDirective, DirectiveElem, DirectiveVariant, ElemWithAttributes, ElemWithContentsBase, ElifAttribute, ElseAttribute, EmittableElem, EnableDirective, ExpressionElem, ExtendedGPUValidationError, FnElem, FnParamElem, FunctionCallExpression, GlobalDeclarationElem, GlobalVarElem, GrammarElem, HasAttributes, Ident, IfAttribute, ImportCollection, ImportElem, ImportItem, ImportSegment, ImportStatement, InterpolateAttribute, LetElem, LexicalScope, LinkConfig, LinkParams, LinkRegistryParams, LinkedWesl, LinkerTransform, Literal, LiveDecls, ManglerFn, ModuleElem, ModuleResolver, NameElem, OverrideElem, ParenthesizedExpression, PartialScope, RecordResolver, RecordResolverOptions, RefIdent, RefIdentElem, RequiresDirective, Scope, SimpleMemberRef, SrcModule, StableState, StandardAttribute, StatementElem, StructElem, StructMemberElem, StuffElem, SwitchClauseElem, SyntheticElem, TerminalElem, TextElem, TransformedAST, TranslateTimeExpressionElem, TranslateTimeFeature, TypeRefElem, TypeTemplateParameter, TypedDeclElem, UnaryExpression, UnaryOperator, UnknownExpressionElem, VarElem, VirtualLibrary, VirtualLibraryFn, VirtualLibrarySet, WeslAST, WeslBundle, WeslDevice, WeslGPUCompilationInfo, WeslGPUCompilationMessage, WeslJsPlugin, WeslParseContext, WeslParseError, WeslParseState, WeslStream, _linkSync, astToString, attributeToString, bindAndTransform, bindIdents, bindIdentsRecursive, bindingStructsPlugin, blankWeslParseState, childIdent, childScope, containsScope, debugContentsToString, emptyScope, errorHighlight, filterMap, findMap, findRefsToBindingStructs, findValidRootDecls, flatImports, groupBy, grouped, identToString, isGlobal, last, lengthPrefixMangle, link, linkRegistry, liveDeclsToString, lowerBindingStructs, makeLiveDecls, makeWeslDevice, mapForward, mapValues, markBindingStructs, markEntryTypes, mergeScope, minimalMangle, minimallyMangledName, multiKeySet, nextIdentId, noSuffix, normalize, normalizeModuleName, offsetToLineNumber, overlapTail, parseSrcModule, partition, publicDecl, replaceWords, requestWeslDevice, resetScopeIds, scan, scopeToString, scopeToStringLong, syntheticWeslParseState, transformBindingReference, transformBindingStruct, underscoreMangle };
1122
+ export { AbstractElem, AbstractElemBase, AliasElem, Attribute, AttributeElem, BatchModuleResolver, BinaryExpression, BinaryOperator, BindIdentsParams, BindResults, BindingAST, BindingStructElem, BoundAndTransformed, BuiltinAttribute, BundleResolver, ComponentExpression, ComponentMemberExpression, CompositeResolver, Conditions, ConstAssertElem, ConstElem, ContainerElem, DeclIdent, DeclIdentElem, DeclarationElem, DiagnosticAttribute, DiagnosticDirective, DirectiveElem, DirectiveVariant, ElemWithAttributes, ElemWithContentsBase, ElifAttribute, ElseAttribute, EmittableElem, EnableDirective, ExpressionElem, ExtendedGPUValidationError, FnElem, FnParamElem, FunctionCallExpression, GlobalDeclarationElem, GlobalVarElem, GrammarElem, HasAttributes, Ident, IfAttribute, ImportCollection, ImportElem, ImportItem, ImportSegment, ImportStatement, InterpolateAttribute, LetElem, LexicalScope, LinkConfig, LinkParams, LinkRegistryParams, LinkedWesl, LinkerTransform, Literal, LiveDecls, ManglerFn, ModuleElem, ModuleResolver, NameElem, OverrideElem, ParenthesizedExpression, PartialScope, RecordResolver, RecordResolverOptions, RefIdent, RefIdentElem, RequiresDirective, Scope, SimpleMemberRef, SrcModule, StableState, StandardAttribute, StatementElem, StructElem, StructMemberElem, StuffElem, SwitchClauseElem, SyntheticElem, TerminalElem, TextElem, TransformedAST, TranslateTimeExpressionElem, TranslateTimeFeature, TypeRefElem, TypeTemplateParameter, TypedDeclElem, UnaryExpression, UnaryOperator, UnknownExpressionElem, VarElem, VirtualLibrary, VirtualLibraryFn, VirtualLibrarySet, WeslAST, WeslBundle, WeslDevice, WeslGPUCompilationInfo, WeslGPUCompilationMessage, WeslJsPlugin, WeslParseContext, WeslParseError, WeslParseState, WeslStream, _linkSync, astToString, attributeToString, bindAndTransform, bindIdents, bindIdentsRecursive, bindingStructsPlugin, blankWeslParseState, childIdent, childScope, containsScope, debugContentsToString, emptyScope, errorHighlight, filterMap, findMap, findRefsToBindingStructs, findUnboundIdents, findValidRootDecls, flatImports, groupBy, grouped, identToString, isGlobal, last, lengthPrefixMangle, link, linkRegistry, liveDeclsToString, lowerBindingStructs, makeLiveDecls, makeWeslDevice, mapForward, mapValues, markBindingStructs, markEntryTypes, mergeScope, minimalMangle, minimallyMangledName, multiKeySet, nextIdentId, noSuffix, normalize, normalizeModuleName, npmNameVariations, offsetToLineNumber, overlapTail, parseSrcModule, partition, publicDecl, replaceWords, requestWeslDevice, resetScopeIds, sanitizePackageName, scan, scopeToString, scopeToStringLong, syntheticWeslParseState, transformBindingReference, transformBindingStruct, underscoreMangle };
package/dist/index.js CHANGED
@@ -2530,7 +2530,7 @@ function findQualifiedImport(refIdent$1, resolver, conditions, virtuals, unbound
2530
2530
  const identParts = refIdent$1.originalName.split("::");
2531
2531
  const modulePathParts = matchingImport(identParts, flatImps) ?? qualifiedIdent(identParts);
2532
2532
  if (!modulePathParts) {
2533
- if (unbound) unbound.push(identParts);
2533
+ if (unbound && !stdWgsl(refIdent$1.originalName)) unbound.push(identParts);
2534
2534
  return;
2535
2535
  }
2536
2536
  const result = findExport(modulePathParts, refIdent$1.ast.srcModule, resolver, conditions, virtuals);
@@ -2623,6 +2623,105 @@ function collectDecls(scope, found) {
2623
2623
  else if (item.kind === "partial") collectDecls(item, found);
2624
2624
  }
2625
2625
 
2626
+ //#endregion
2627
+ //#region src/discovery/FindUnboundIdents.ts
2628
+ /**
2629
+ * Find unbound package references in library sources.
2630
+ *
2631
+ * Binds local references without following cross-package imports, revealing
2632
+ * which external packages are referenced but not resolved.
2633
+ *
2634
+ * @param resolver - Module resolver that supports batch operations
2635
+ * @returns Array of unbound module paths, each as an array of path segments
2636
+ * (e.g., [['foo', 'bar', 'baz'], ['other', 'pkg']])
2637
+ */
2638
+ function findUnboundIdents(resolver) {
2639
+ const bindContext = {
2640
+ resolver,
2641
+ conditions: {},
2642
+ knownDecls: /* @__PURE__ */ new Set(),
2643
+ foundScopes: /* @__PURE__ */ new Set(),
2644
+ globalNames: /* @__PURE__ */ new Set(),
2645
+ globalStatements: /* @__PURE__ */ new Map(),
2646
+ mangler: minimalMangle,
2647
+ unbound: [],
2648
+ dontFollowDecls: true
2649
+ };
2650
+ for (const [_modulePath, ast] of resolver.allModules()) {
2651
+ const declEntries = findValidRootDecls(ast.rootScope, {}).map((d) => [d.originalName, d]);
2652
+ const liveDecls = {
2653
+ decls: new Map(declEntries),
2654
+ parent: null
2655
+ };
2656
+ bindIdentsRecursive(ast.rootScope, bindContext, liveDecls, true);
2657
+ }
2658
+ return bindContext.unbound;
2659
+ }
2660
+
2661
+ //#endregion
2662
+ //#region src/discovery/PackageNameUtils.ts
2663
+ /** Package name sanitization for WESL.
2664
+ *
2665
+ * Converts typical npm package names to WGSL-safe identifiers using double-underscore encoding.
2666
+ * NPM package names can contain `@`, `/`, and `-`, which are not allowed in WGSL identifiers.
2667
+ *
2668
+ * ## Encoding Scheme
2669
+ *
2670
+ * ```
2671
+ * @ ==> (remove)
2672
+ * / ==> __ (double underscore)
2673
+ * - ==> _ (single underscore)
2674
+ * ```
2675
+ *
2676
+ * ## Forward Mapping (npm ==> WGSL identifier)
2677
+ *
2678
+ * ```
2679
+ * my_package ==> my_package
2680
+ * random-wgsl ==> random_wgsl
2681
+ * @scope/my-pkg ==> scope__my_pkg
2682
+ * ```
2683
+ *
2684
+ * ## Reverse Mapping (WGSL identifier ==> npm package)
2685
+ *
2686
+ * ```
2687
+ * scope__my_pkg ==> try: @scope/my_pkg, @scope/my-pkg
2688
+ * random_wgsl ==> try: random_wgsl, random-wgsl
2689
+ * ```
2690
+ */
2691
+ /** Convert npm package name to WGSL-safe identifier using double-underscore encoding. */
2692
+ function sanitizePackageName(npmName) {
2693
+ return npmName.replace(/^@/, "").replaceAll("/", "__").replaceAll("-", "_");
2694
+ }
2695
+ /** Generate npm package name variations from sanitized WESL identifier.
2696
+ *
2697
+ * Uses double-underscore encoding to distinguish scoped vs unscoped packages:
2698
+ * - Has __ → scoped package (try @scope/pkg variants)
2699
+ * - No __ → unscoped package (try pkg variants)
2700
+ *
2701
+ * Examples:
2702
+ * "lygia__shader_utils" → ["@lygia/shader_utils", "@lygia/shader-utils"]
2703
+ * "random_wgsl" → ["random_wgsl", "random-wgsl"]
2704
+ */
2705
+ function* npmNameVariations(sanitizedPath) {
2706
+ const [pkg, sub] = breakAt(sanitizedPath, "/");
2707
+ let pkgName = pkg;
2708
+ let scopePrefix = "";
2709
+ if (pkg.includes("__")) {
2710
+ const [scope, ...rest] = pkg.split("__");
2711
+ pkgName = rest.join("__");
2712
+ scopePrefix = `@${scope}/`;
2713
+ }
2714
+ yield `${scopePrefix}${pkgName}${sub}`;
2715
+ yield `${scopePrefix}${pkgName.replaceAll("_", "-")}${sub}`;
2716
+ }
2717
+ /** Break string at first occurrence of delimiter.
2718
+ * @returns [before, after] where after includes the delimiter */
2719
+ function breakAt(str, delimiter) {
2720
+ const index = str.indexOf(delimiter);
2721
+ if (index === -1) return [str, ""];
2722
+ return [str.slice(0, index), str.slice(index)];
2723
+ }
2724
+
2626
2725
  //#endregion
2627
2726
  //#region src/LinkedWesl.ts
2628
2727
  /**
@@ -3387,4 +3486,4 @@ function makeWeslDevice(device) {
3387
3486
  }
3388
3487
 
3389
3488
  //#endregion
3390
- export { BundleResolver, CompositeResolver, LinkedWesl, RecordResolver, WeslParseError, WeslStream, _linkSync, astToString, attributeToString, bindAndTransform, bindIdents, bindIdentsRecursive, bindingStructsPlugin, blankWeslParseState, childIdent, childScope, containsScope, debugContentsToString, emptyScope, errorHighlight, filterMap, findMap, findRefsToBindingStructs, findValidRootDecls, flatImports, groupBy, grouped, identToString, isGlobal, last, lengthPrefixMangle, link, linkRegistry, liveDeclsToString, lowerBindingStructs, makeLiveDecls, makeWeslDevice, mapForward, mapValues, markBindingStructs, markEntryTypes, mergeScope, minimalMangle, minimallyMangledName, multiKeySet, nextIdentId, noSuffix, normalize, normalizeModuleName, offsetToLineNumber, overlapTail, parseSrcModule, partition, publicDecl, replaceWords, requestWeslDevice, resetScopeIds, scan, scopeToString, scopeToStringLong, syntheticWeslParseState, transformBindingReference, transformBindingStruct, underscoreMangle };
3489
+ export { BundleResolver, CompositeResolver, LinkedWesl, RecordResolver, WeslParseError, WeslStream, _linkSync, astToString, attributeToString, bindAndTransform, bindIdents, bindIdentsRecursive, bindingStructsPlugin, blankWeslParseState, childIdent, childScope, containsScope, debugContentsToString, emptyScope, errorHighlight, filterMap, findMap, findRefsToBindingStructs, findUnboundIdents, findValidRootDecls, flatImports, groupBy, grouped, identToString, isGlobal, last, lengthPrefixMangle, link, linkRegistry, liveDeclsToString, lowerBindingStructs, makeLiveDecls, makeWeslDevice, mapForward, mapValues, markBindingStructs, markEntryTypes, mergeScope, minimalMangle, minimallyMangledName, multiKeySet, nextIdentId, noSuffix, normalize, normalizeModuleName, npmNameVariations, offsetToLineNumber, overlapTail, parseSrcModule, partition, publicDecl, replaceWords, requestWeslDevice, resetScopeIds, sanitizePackageName, scan, scopeToString, scopeToStringLong, syntheticWeslParseState, transformBindingReference, transformBindingStruct, underscoreMangle };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wesl",
3
- "version": "0.6.46",
3
+ "version": "0.6.48",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -11,11 +11,14 @@
11
11
  ".": {
12
12
  "types": "./dist/index.d.ts",
13
13
  "import": "./dist/index.js"
14
+ },
15
+ "./bundle-decl": {
16
+ "import": "./src/weslBundleDeclUrl.ts"
14
17
  }
15
18
  },
16
19
  "types": "dist/index.d.ts",
17
20
  "dependencies": {
18
- "mini-parse": "0.6.40"
21
+ "mini-parse": "0.6.41"
19
22
  },
20
23
  "devDependencies": {
21
24
  "@types/brotli": "^1.3.4",
package/src/BindIdents.ts CHANGED
@@ -434,7 +434,7 @@ function findQualifiedImport(
434
434
  matchingImport(identParts, flatImps) ?? qualifiedIdent(identParts);
435
435
 
436
436
  if (!modulePathParts) {
437
- if (unbound) unbound.push(identParts);
437
+ if (unbound && !stdWgsl(refIdent.originalName)) unbound.push(identParts);
438
438
  return undefined;
439
439
  }
440
440
 
@@ -75,7 +75,7 @@ export function throwClickableError(params: ClickableErrorParams): void {
75
75
  let oldLimit = 0;
76
76
  // Supported on Chrome https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/stackTraceLimit
77
77
  if ("stackTraceLimit" in Error) {
78
- oldLimit = Error.stackTraceLimit;
78
+ oldLimit = Error.stackTraceLimit as number;
79
79
  Error.stackTraceLimit = 1;
80
80
  }
81
81
 
@@ -0,0 +1,43 @@
1
+ import type { AbstractElem } from "../AbstractElems.ts";
2
+ import {
3
+ bindIdentsRecursive,
4
+ type EmittableElem,
5
+ findValidRootDecls,
6
+ } from "../BindIdents.ts";
7
+ import type { LiveDecls } from "../LiveDeclarations.ts";
8
+ import { minimalMangle } from "../Mangler.ts";
9
+ import type { BatchModuleResolver } from "../ModuleResolver.ts";
10
+ import type { DeclIdent, Scope } from "../Scope.ts";
11
+
12
+ /**
13
+ * Find unbound package references in library sources.
14
+ *
15
+ * Binds local references without following cross-package imports, revealing
16
+ * which external packages are referenced but not resolved.
17
+ *
18
+ * @param resolver - Module resolver that supports batch operations
19
+ * @returns Array of unbound module paths, each as an array of path segments
20
+ * (e.g., [['foo', 'bar', 'baz'], ['other', 'pkg']])
21
+ */
22
+ export function findUnboundIdents(resolver: BatchModuleResolver): string[][] {
23
+ const bindContext = {
24
+ resolver,
25
+ conditions: {},
26
+ knownDecls: new Set<DeclIdent>(),
27
+ foundScopes: new Set<Scope>(),
28
+ globalNames: new Set<string>(),
29
+ globalStatements: new Map<AbstractElem, EmittableElem>(),
30
+ mangler: minimalMangle,
31
+ unbound: [] as string[][],
32
+ dontFollowDecls: true,
33
+ };
34
+
35
+ for (const [_modulePath, ast] of resolver.allModules()) {
36
+ const rootDecls = findValidRootDecls(ast.rootScope, {});
37
+ const declEntries = rootDecls.map(d => [d.originalName, d] as const);
38
+ const liveDecls: LiveDecls = { decls: new Map(declEntries), parent: null };
39
+ bindIdentsRecursive(ast.rootScope, bindContext, liveDecls, true);
40
+ }
41
+
42
+ return bindContext.unbound;
43
+ }
@@ -0,0 +1,71 @@
1
+ /** Package name sanitization for WESL.
2
+ *
3
+ * Converts typical npm package names to WGSL-safe identifiers using double-underscore encoding.
4
+ * NPM package names can contain `@`, `/`, and `-`, which are not allowed in WGSL identifiers.
5
+ *
6
+ * ## Encoding Scheme
7
+ *
8
+ * ```
9
+ * @ ==> (remove)
10
+ * / ==> __ (double underscore)
11
+ * - ==> _ (single underscore)
12
+ * ```
13
+ *
14
+ * ## Forward Mapping (npm ==> WGSL identifier)
15
+ *
16
+ * ```
17
+ * my_package ==> my_package
18
+ * random-wgsl ==> random_wgsl
19
+ * @scope/my-pkg ==> scope__my_pkg
20
+ * ```
21
+ *
22
+ * ## Reverse Mapping (WGSL identifier ==> npm package)
23
+ *
24
+ * ```
25
+ * scope__my_pkg ==> try: @scope/my_pkg, @scope/my-pkg
26
+ * random_wgsl ==> try: random_wgsl, random-wgsl
27
+ * ```
28
+ */
29
+
30
+ /** Convert npm package name to WGSL-safe identifier using double-underscore encoding. */
31
+ export function sanitizePackageName(npmName: string): string {
32
+ return npmName
33
+ .replace(/^@/, "") // Remove @ prefix
34
+ .replaceAll("/", "__") // Replace / with __ (double underscore)
35
+ .replaceAll("-", "_"); // Replace - with _ (single underscore)
36
+ }
37
+
38
+ /** Generate npm package name variations from sanitized WESL identifier.
39
+ *
40
+ * Uses double-underscore encoding to distinguish scoped vs unscoped packages:
41
+ * - Has __ → scoped package (try @scope/pkg variants)
42
+ * - No __ → unscoped package (try pkg variants)
43
+ *
44
+ * Examples:
45
+ * "lygia__shader_utils" → ["@lygia/shader_utils", "@lygia/shader-utils"]
46
+ * "random_wgsl" → ["random_wgsl", "random-wgsl"]
47
+ */
48
+ export function* npmNameVariations(sanitizedPath: string): Generator<string> {
49
+ const [pkg, sub] = breakAt(sanitizedPath, "/");
50
+
51
+ let pkgName = pkg;
52
+ let scopePrefix = "";
53
+
54
+ if (pkg.includes("__")) {
55
+ // presume a scoped npm package (@scope/pkg)
56
+ const [scope, ...rest] = pkg.split("__");
57
+ pkgName = rest.join("__"); // Rejoin in case of __ in package name (rare)
58
+ scopePrefix = `@${scope}/`;
59
+ }
60
+
61
+ yield `${scopePrefix}${pkgName}${sub}`;
62
+ yield `${scopePrefix}${pkgName.replaceAll("_", "-")}${sub}`;
63
+ }
64
+
65
+ /** Break string at first occurrence of delimiter.
66
+ * @returns [before, after] where after includes the delimiter */
67
+ function breakAt(str: string, delimiter: string): [string, string] {
68
+ const index = str.indexOf(delimiter);
69
+ if (index === -1) return [str, ""];
70
+ return [str.slice(0, index), str.slice(index)];
71
+ }
package/src/index.ts CHANGED
@@ -2,6 +2,8 @@ export * from "./AbstractElems.ts";
2
2
  export * from "./BindIdents.ts";
3
3
  export * from "./debug/ASTtoString.ts";
4
4
  export * from "./debug/ScopeToString.ts";
5
+ export * from "./discovery/FindUnboundIdents.ts";
6
+ export * from "./discovery/PackageNameUtils.ts";
5
7
  export * from "./LinkedWesl.ts";
6
8
  export * from "./Linker.ts";
7
9
  export * from "./LiveDeclarations.ts";
@@ -3,7 +3,7 @@ import { testLink } from "./TestLink.ts";
3
3
 
4
4
  // LATER move these to cond cases? (or drop if duplicative)
5
5
 
6
- test("conditional statement", async () => {
6
+ test("conditional declaration ", async () => {
7
7
  const app = `
8
8
  fn main() {
9
9
  @if(false) let x = 1;
@@ -17,6 +17,22 @@ test("conditional statement", async () => {
17
17
  await testLink({ app: app }, "app", expectWgsl);
18
18
  });
19
19
 
20
+ test("conditional assignment", async () => {
21
+ const app = `
22
+ fn main() {
23
+ var x = 1;
24
+ @if(false) x = 2;
25
+ }
26
+ `;
27
+
28
+ const expectWgsl = `
29
+ fn main() {
30
+ var x = 1;
31
+ }
32
+ `;
33
+ await testLink({ app: app }, "app", expectWgsl);
34
+ });
35
+
20
36
  test("conditional compound statement", async () => {
21
37
  const app = `
22
38
  fn main() {
@@ -0,0 +1,32 @@
1
+ import { expect, test } from "vitest";
2
+ import { sanitizePackageName } from "../discovery/PackageNameUtils.ts";
3
+
4
+ test("my_package", () => {
5
+ expect(sanitizePackageName("my_package")).toBe("my_package");
6
+ });
7
+
8
+ test("my-package", () => {
9
+ expect(sanitizePackageName("my-package")).toBe("my_package");
10
+ });
11
+
12
+ test("my-cool-package", () => {
13
+ expect(sanitizePackageName("my-cool-package")).toBe("my_cool_package");
14
+ });
15
+
16
+ test("@scope/package", () => {
17
+ expect(sanitizePackageName("@scope/package")).toBe("scope__package");
18
+ });
19
+
20
+ test("@scope/my-package", () => {
21
+ expect(sanitizePackageName("@scope/my-package")).toBe("scope__my_package");
22
+ });
23
+
24
+ test("@scope/my_package", () => {
25
+ expect(sanitizePackageName("@scope/my_package")).toBe("scope__my_package");
26
+ });
27
+
28
+ test("@my-org/my-cool-package", () => {
29
+ expect(sanitizePackageName("@my-org/my-cool-package")).toBe(
30
+ "my_org__my_cool_package",
31
+ );
32
+ });
@@ -0,0 +1,2 @@
1
+ export const weslBundleDeclUrl = new URL("./WeslBundle.ts", import.meta.url)
2
+ .href;