unplugin-typegpu 0.9.0 → 0.10.0
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/babel.cjs +161 -2
- package/babel.d.cts +8 -7
- package/babel.d.cts.map +1 -0
- package/babel.d.mts +12 -0
- package/babel.d.mts.map +1 -0
- package/babel.mjs +159 -0
- package/babel.mjs.map +1 -0
- package/bun.cjs +39 -2
- package/bun.d.cts +6 -3
- package/bun.d.cts.map +1 -0
- package/bun.d.mts +7 -0
- package/bun.d.mts.map +1 -0
- package/bun.mjs +37 -0
- package/bun.mjs.map +1 -0
- package/common-CRPQ2KE6.d.mts +26 -0
- package/common-CRPQ2KE6.d.mts.map +1 -0
- package/common-Dpl8jppn.d.cts +26 -0
- package/common-Dpl8jppn.d.cts.map +1 -0
- package/esbuild.cjs +8 -2
- package/esbuild.d.cts +3 -14
- package/esbuild.d.mts +4 -0
- package/esbuild.mjs +8 -0
- package/esbuild.mjs.map +1 -0
- package/farm.cjs +8 -2
- package/farm.d.cts +3 -14
- package/farm.d.mts +4 -0
- package/farm.mjs +8 -0
- package/farm.mjs.map +1 -0
- package/filter-6T-5w4kG.mjs +235 -0
- package/filter-6T-5w4kG.mjs.map +1 -0
- package/filter-CKmD4HRk.cjs +327 -0
- package/index-legacy-DRI9LQiG.d.mts +1489 -0
- package/index-legacy-DRI9LQiG.d.mts.map +1 -0
- package/index-legacy-xKi5C2ga.d.cts +1489 -0
- package/index-legacy-xKi5C2ga.d.cts.map +1 -0
- package/index.cjs +29 -2
- package/index.d.cts +12 -48
- package/index.d.cts.map +1 -0
- package/index.d.mts +18 -0
- package/index.d.mts.map +1 -0
- package/index.mjs +18 -0
- package/index.mjs.map +1 -0
- package/package.json +95 -51
- package/rolldown-browser-DKeiFM_e.mjs +130 -0
- package/rolldown-browser-DKeiFM_e.mjs.map +1 -0
- package/rolldown-browser-DUanNY-R.cjs +141 -0
- package/rolldown-browser-JYqfNLQ8.d.mts +1248 -0
- package/rolldown-browser-JYqfNLQ8.d.mts.map +1 -0
- package/rolldown.cjs +8 -2
- package/rolldown.d.cts +3 -14
- package/rolldown.d.mts +4 -0
- package/rolldown.mjs +8 -0
- package/rolldown.mjs.map +1 -0
- package/rollup-impl-DqC_d-_W.d.cts +1247 -0
- package/rollup-impl-DqC_d-_W.d.cts.map +1 -0
- package/rollup.cjs +8 -2
- package/rollup.d.cts +3 -14
- package/rollup.d.mts +4 -0
- package/rollup.mjs +8 -0
- package/rollup.mjs.map +1 -0
- package/rspack.cjs +8 -2
- package/rspack.d.cts +3 -14
- package/rspack.d.mts +4 -0
- package/rspack.mjs +8 -0
- package/rspack.mjs.map +1 -0
- package/vite.cjs +8 -2
- package/vite.d.cts +3 -14
- package/vite.d.mts +4 -0
- package/vite.mjs +8 -0
- package/vite.mjs.map +1 -0
- package/webpack.cjs +8 -2
- package/webpack.d.cts +3 -14
- package/webpack.d.mts +4 -0
- package/webpack.mjs +8 -0
- package/webpack.mjs.map +1 -0
- package/babel.cjs.map +0 -1
- package/babel.d.ts +0 -10
- package/babel.js +0 -2
- package/babel.js.map +0 -1
- package/bun-Dq3TUCfa.d.cts +0 -27
- package/bun-Dq3TUCfa.d.ts +0 -27
- package/bun.cjs.map +0 -1
- package/bun.d.ts +0 -3
- package/bun.js +0 -2
- package/bun.js.map +0 -1
- package/chunk-DEVVEJF4.cjs +0 -2
- package/chunk-DEVVEJF4.cjs.map +0 -1
- package/chunk-EESBB3Y4.js +0 -2
- package/chunk-EESBB3Y4.js.map +0 -1
- package/chunk-LJXNN2RM.cjs +0 -7
- package/chunk-LJXNN2RM.cjs.map +0 -1
- package/chunk-NQODVO3L.cjs +0 -2
- package/chunk-NQODVO3L.cjs.map +0 -1
- package/chunk-RIZD7OMC.js +0 -7
- package/chunk-RIZD7OMC.js.map +0 -1
- package/chunk-V4Q4PLLO.js +0 -2
- package/chunk-V4Q4PLLO.js.map +0 -1
- package/esbuild.cjs.map +0 -1
- package/esbuild.d.ts +0 -14
- package/esbuild.js +0 -2
- package/esbuild.js.map +0 -1
- package/farm.cjs.map +0 -1
- package/farm.d.ts +0 -14
- package/farm.js +0 -2
- package/farm.js.map +0 -1
- package/index.cjs.map +0 -1
- package/index.d.ts +0 -54
- package/index.js +0 -2
- package/index.js.map +0 -1
- package/rolldown.cjs.map +0 -1
- package/rolldown.d.ts +0 -14
- package/rolldown.js +0 -2
- package/rolldown.js.map +0 -1
- package/rollup.cjs.map +0 -1
- package/rollup.d.ts +0 -14
- package/rollup.js +0 -2
- package/rollup.js.map +0 -1
- package/rspack.cjs.map +0 -1
- package/rspack.d.ts +0 -14
- package/rspack.js +0 -2
- package/rspack.js.map +0 -1
- package/vite.cjs.map +0 -1
- package/vite.d.ts +0 -14
- package/vite.js +0 -2
- package/vite.js.map +0 -1
- package/webpack.cjs.map +0 -1
- package/webpack.d.ts +0 -14
- package/webpack.js +0 -2
- package/webpack.js.map +0 -1
package/farm.d.cts
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import 'unplugin';
|
|
5
|
-
import './bun-Dq3TUCfa.cjs';
|
|
6
|
-
import 'bun';
|
|
7
|
-
import './babel.cjs';
|
|
8
|
-
import '@babel/traverse';
|
|
9
|
-
import '@babel/types';
|
|
10
|
-
import 'magic-string-ast';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export { farmPlugin as default };
|
|
1
|
+
import "./rollup-impl-DqC_d-_W.cjs";
|
|
2
|
+
import { farmPlugin } from "./index.cjs";
|
|
3
|
+
export = farmPlugin;
|
package/farm.d.mts
ADDED
package/farm.mjs
ADDED
package/farm.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"farm.mjs","names":[],"sources":["../src/farm.ts"],"sourcesContent":["import { farmPlugin } from './index.ts';\n\nexport default farmPlugin;\n"],"mappings":";;;AAEA,mBAAe"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { resolve } from "pathe";
|
|
2
|
+
import picomatch from "picomatch";
|
|
3
|
+
|
|
4
|
+
//#region src/common.ts
|
|
5
|
+
const defaultOptions = {
|
|
6
|
+
include: /\.m?[jt]sx?(?:\?.*)?$/,
|
|
7
|
+
autoNamingEnabled: true,
|
|
8
|
+
earlyPruning: true
|
|
9
|
+
};
|
|
10
|
+
function embedJSON(jsValue) {
|
|
11
|
+
return JSON.stringify(jsValue).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Checks if `node` is an alias for the 'tgpu' object, traditionally
|
|
15
|
+
* available via `import tgpu from 'typegpu'`.
|
|
16
|
+
*/
|
|
17
|
+
function isTgpu(ctx, node) {
|
|
18
|
+
let path = "";
|
|
19
|
+
let tail = node;
|
|
20
|
+
while (true) if (tail.type === "MemberExpression") {
|
|
21
|
+
if ((tail.property.type === "Literal" || tail.property.type === "StringLiteral") && tail.property.value === "~unstable") {
|
|
22
|
+
tail = tail.object;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (tail.property.type !== "Identifier") break;
|
|
26
|
+
path = path ? `${tail.property.name}.${path}` : tail.property.name;
|
|
27
|
+
tail = tail.object;
|
|
28
|
+
} else if (tail.type === "Identifier") {
|
|
29
|
+
path = path ? `${tail.name}.${path}` : tail.name;
|
|
30
|
+
break;
|
|
31
|
+
} else break;
|
|
32
|
+
return ctx.tgpuAliases.has(path);
|
|
33
|
+
}
|
|
34
|
+
function gatherTgpuAliases(node, ctx) {
|
|
35
|
+
if (node.source.value === "typegpu") {
|
|
36
|
+
for (const spec of node.specifiers) if (spec.type === "ImportDefaultSpecifier" || spec.type === "ImportSpecifier" && spec.imported.type === "Identifier" && spec.imported.name === "tgpu") ctx.tgpuAliases.add(spec.local.name);
|
|
37
|
+
else if (spec.type === "ImportNamespaceSpecifier") ctx.tgpuAliases.add(`${spec.local.name}.tgpu`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const fnShellFunctionNames = [
|
|
41
|
+
"fn",
|
|
42
|
+
"vertexFn",
|
|
43
|
+
"fragmentFn",
|
|
44
|
+
"computeFn"
|
|
45
|
+
];
|
|
46
|
+
function isShellImplementationCall(node, ctx) {
|
|
47
|
+
return node.callee.type === "CallExpression" && node.callee.callee.type === "MemberExpression" && node.callee.callee.property.type === "Identifier" && fnShellFunctionNames.includes(node.callee.callee.property.name) && node.arguments.length === 1 && isTgpu(ctx, node.callee.callee.object);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Extracts a name and expression from nodes that contain a label and an expression,
|
|
51
|
+
* such as VariableDeclarator or PropertyDefinition.
|
|
52
|
+
* Returns a tuple of [name, expression] if found, otherwise undefined.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* extractLabelledExpression(node`let name = tgpu.bindGroupLayout({});`)
|
|
56
|
+
* // ["name", node`tgpu.bindGroupLayout({})`]
|
|
57
|
+
*/
|
|
58
|
+
function extractLabelledExpression(node) {
|
|
59
|
+
if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init) return [node.id.name, node.init];
|
|
60
|
+
else if (node.type === "AssignmentExpression") {
|
|
61
|
+
const maybeName = tryFindIdentifier(node.left);
|
|
62
|
+
if (maybeName) return [maybeName, node.right];
|
|
63
|
+
} else if ((node.type === "Property" || node.type === "ObjectProperty") && node.key.type === "Identifier") return [node.key.name, node.value];
|
|
64
|
+
else if ((node.type === "ClassProperty" || node.type === "PropertyDefinition") && node.value && node.key.type === "Identifier") return [node.key.name, node.value];
|
|
65
|
+
}
|
|
66
|
+
function getFunctionName(node, parent) {
|
|
67
|
+
var _extractLabelledExpre, _node$id;
|
|
68
|
+
const maybeName = parent ? (_extractLabelledExpre = extractLabelledExpression(parent)) === null || _extractLabelledExpre === void 0 ? void 0 : _extractLabelledExpre[0] : void 0;
|
|
69
|
+
return maybeName !== null && maybeName !== void 0 ? maybeName : node.type === "FunctionDeclaration" || node.type === "FunctionExpression" ? (_node$id = node.id) === null || _node$id === void 0 ? void 0 : _node$id.name : void 0;
|
|
70
|
+
}
|
|
71
|
+
const resourceConstructors = [
|
|
72
|
+
"bindGroupLayout",
|
|
73
|
+
"vertexLayout",
|
|
74
|
+
"privateVar",
|
|
75
|
+
"workgroupVar",
|
|
76
|
+
"const",
|
|
77
|
+
"slot",
|
|
78
|
+
"accessor",
|
|
79
|
+
"comptime",
|
|
80
|
+
...fnShellFunctionNames,
|
|
81
|
+
"createBuffer",
|
|
82
|
+
"createMutable",
|
|
83
|
+
"createReadonly",
|
|
84
|
+
"createUniform",
|
|
85
|
+
"createQuerySet",
|
|
86
|
+
"createPipeline",
|
|
87
|
+
"createComputePipeline",
|
|
88
|
+
"createGuardedComputePipeline",
|
|
89
|
+
"createRenderPipeline",
|
|
90
|
+
"createTexture",
|
|
91
|
+
"createSampler",
|
|
92
|
+
"createComparisonSampler",
|
|
93
|
+
"struct",
|
|
94
|
+
"unstruct",
|
|
95
|
+
"createView"
|
|
96
|
+
];
|
|
97
|
+
/**
|
|
98
|
+
* Checks if `node` should be wrapped in an autoname function.
|
|
99
|
+
* Since it is mostly for debugging and clean WGSL generation,
|
|
100
|
+
* some false positives and false negatives are admissible.
|
|
101
|
+
*/
|
|
102
|
+
function containsResourceConstructorCall(node, ctx) {
|
|
103
|
+
if (node.type === "CallExpression") {
|
|
104
|
+
if (isShellImplementationCall(node, ctx)) return true;
|
|
105
|
+
if (node.callee.type === "Identifier" && resourceConstructors.includes(node.callee.name)) return true;
|
|
106
|
+
if (node.callee.type === "MemberExpression") {
|
|
107
|
+
if (node.callee.property.type === "Identifier") {
|
|
108
|
+
if (resourceConstructors.includes(node.callee.property.name)) return true;
|
|
109
|
+
if (node.callee.property.name === "$name") return false;
|
|
110
|
+
}
|
|
111
|
+
return containsResourceConstructorCall(node.callee.object, ctx);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (node.type === "TaggedTemplateExpression") return containsResourceConstructorCall(node.tag, ctx);
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Tries to find an identifier in a node.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* // syntax is simplified, imagine the arguments are appropriate nodes instead
|
|
122
|
+
* tryFindIdentifier('myBuffer'); // 'myBuffer'
|
|
123
|
+
* tryFindIdentifier('buffers.myBuffer'); // 'myBuffer'
|
|
124
|
+
* tryFindIdentifier('this.myBuffer'); // 'myBuffer'
|
|
125
|
+
* tryFindIdentifier('[a, b]'); // undefined
|
|
126
|
+
*/
|
|
127
|
+
function tryFindIdentifier(node) {
|
|
128
|
+
if (node.type === "Identifier") return node.name;
|
|
129
|
+
if (node.type === "PrivateName") return tryFindIdentifier(node.id);
|
|
130
|
+
if (node.type === "PrivateIdentifier") return node.name;
|
|
131
|
+
if (node.type === "MemberExpression") return tryFindIdentifier(node.property);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Checks if `node` contains a label and a tgpu expression that could be named.
|
|
135
|
+
* If so, it calls the provided callback. Nodes selected for naming include:
|
|
136
|
+
*
|
|
137
|
+
* `let name = tgpu.bindGroupLayout({});` (VariableDeclarator)
|
|
138
|
+
*
|
|
139
|
+
* `name = tgpu.bindGroupLayout({});` (AssignmentExpression)
|
|
140
|
+
*
|
|
141
|
+
* `property: tgpu.bindGroupLayout({})` (Property/ObjectProperty)
|
|
142
|
+
*
|
|
143
|
+
* Since it is mostly for debugging and clean WGSL generation,
|
|
144
|
+
* some false positives and false negatives are admissible.
|
|
145
|
+
*
|
|
146
|
+
* This function is NOT used for auto-naming shell-less functions.
|
|
147
|
+
* Those are handled separately.
|
|
148
|
+
*
|
|
149
|
+
* @privateRemarks
|
|
150
|
+
* When adding new checks, you need to call this method in the corresponding node in Babel.
|
|
151
|
+
*/
|
|
152
|
+
function performExpressionNaming(ctx, node, namingCallback) {
|
|
153
|
+
if (!ctx.autoNamingEnabled) return;
|
|
154
|
+
const labelledExpression = extractLabelledExpression(node);
|
|
155
|
+
if (labelledExpression) {
|
|
156
|
+
const [label, expression] = labelledExpression;
|
|
157
|
+
if (containsResourceConstructorCall(expression, ctx)) namingCallback(expression, label);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const useGpuDirective = "use gpu";
|
|
161
|
+
/** Regular expressions used for early pruning (to avoid unnecessary parsing, which is expensive) */
|
|
162
|
+
const earlyPruneRegex = [/["']use gpu["']/, /t(ype)?gpu/];
|
|
163
|
+
const operators = {
|
|
164
|
+
"+": "__tsover_add",
|
|
165
|
+
"-": "__tsover_sub",
|
|
166
|
+
"*": "__tsover_mul",
|
|
167
|
+
"/": "__tsover_div",
|
|
168
|
+
"%": "__tsover_mod",
|
|
169
|
+
"+=": "__tsover_add",
|
|
170
|
+
"-=": "__tsover_sub",
|
|
171
|
+
"*=": "__tsover_mul",
|
|
172
|
+
"/=": "__tsover_div",
|
|
173
|
+
"%=": "__tsover_mod"
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/filter.ts
|
|
178
|
+
function toArray(array) {
|
|
179
|
+
const result = array || [];
|
|
180
|
+
if (Array.isArray(result)) return result;
|
|
181
|
+
return [result];
|
|
182
|
+
}
|
|
183
|
+
const BACKSLASH_REGEX = /\\/g;
|
|
184
|
+
function normalize(path) {
|
|
185
|
+
return path.replace(BACKSLASH_REGEX, "/");
|
|
186
|
+
}
|
|
187
|
+
const ABSOLUTE_PATH_REGEX = /^(?:\/|(?:[A-Z]:)?[/\\|])/i;
|
|
188
|
+
function isAbsolute(path) {
|
|
189
|
+
return ABSOLUTE_PATH_REGEX.test(path);
|
|
190
|
+
}
|
|
191
|
+
function getMatcherString(glob, cwd) {
|
|
192
|
+
if (glob.startsWith("**") || isAbsolute(glob)) return normalize(glob);
|
|
193
|
+
return normalize(resolve(cwd, glob));
|
|
194
|
+
}
|
|
195
|
+
function patternToIdFilter(pattern) {
|
|
196
|
+
if (pattern instanceof RegExp) return (id) => {
|
|
197
|
+
const normalizedId = normalize(id);
|
|
198
|
+
const result = pattern.test(normalizedId);
|
|
199
|
+
pattern.lastIndex = 0;
|
|
200
|
+
return result;
|
|
201
|
+
};
|
|
202
|
+
const matcher = picomatch(getMatcherString(pattern, process.cwd()), { dot: true });
|
|
203
|
+
return (id) => {
|
|
204
|
+
return matcher(normalize(id));
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function createFilter(exclude, include) {
|
|
208
|
+
if (!exclude && !include) return;
|
|
209
|
+
return (input) => {
|
|
210
|
+
if (exclude === null || exclude === void 0 ? void 0 : exclude.some((filter) => filter(input))) return false;
|
|
211
|
+
if (include === null || include === void 0 ? void 0 : include.some((filter) => filter(input))) return true;
|
|
212
|
+
return !(include && include.length > 0);
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function normalizeFilter(filter) {
|
|
216
|
+
if (typeof filter === "string" || filter instanceof RegExp) return { include: [filter] };
|
|
217
|
+
if (Array.isArray(filter)) return { include: filter };
|
|
218
|
+
return {
|
|
219
|
+
exclude: filter.exclude ? toArray(filter.exclude) : void 0,
|
|
220
|
+
include: filter.include ? toArray(filter.include) : void 0
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function createIdFilter(filter) {
|
|
224
|
+
if (!filter) return;
|
|
225
|
+
const { exclude, include } = normalizeFilter(filter);
|
|
226
|
+
return createFilter(exclude === null || exclude === void 0 ? void 0 : exclude.map(patternToIdFilter), include === null || include === void 0 ? void 0 : include.map(patternToIdFilter));
|
|
227
|
+
}
|
|
228
|
+
function createFilterForId(filter) {
|
|
229
|
+
const filterFunction = createIdFilter(filter);
|
|
230
|
+
return filterFunction ? (id) => !!filterFunction(id) : void 0;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
//#endregion
|
|
234
|
+
export { gatherTgpuAliases as a, operators as c, embedJSON as i, performExpressionNaming as l, defaultOptions as n, getFunctionName as o, earlyPruneRegex as r, isShellImplementationCall as s, createFilterForId as t, useGpuDirective as u };
|
|
235
|
+
//# sourceMappingURL=filter-6T-5w4kG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-6T-5w4kG.mjs","names":[],"sources":["../src/common.ts","../src/filter.ts"],"sourcesContent":["import type * as babel from '@babel/types';\nimport type * as acorn from 'acorn';\nimport type { FilterPattern } from 'unplugin';\n\nexport type Context = {\n /**\n * How the `tgpu` object is used in code. Since it can be aliased, we\n * need to catch that and act accordingly.\n */\n tgpuAliases: Set<string>;\n fileId?: string | undefined;\n autoNamingEnabled: boolean;\n};\n\nexport interface Options {\n /** @default [/\\.m?[jt]sx?$/] */\n include?: FilterPattern;\n\n /** @default undefined */\n exclude?: FilterPattern;\n\n /** @default undefined */\n enforce?: 'post' | 'pre' | undefined;\n\n /** @default undefined */\n forceTgpuAlias?: string | undefined;\n\n /** @default true */\n autoNamingEnabled?: boolean | undefined;\n\n /**\n * Skipping files that don't contain \"typegpu\", \"tgpu\" or \"use gpu\".\n * In case this early pruning hinders transformation, you\n * can disable it.\n *\n * @default true\n */\n earlyPruning?: boolean | undefined;\n}\n\nexport const defaultOptions = {\n include: /\\.m?[jt]sx?(?:\\?.*)?$/,\n autoNamingEnabled: true,\n earlyPruning: true,\n};\n\nexport function embedJSON(jsValue: unknown) {\n return JSON.stringify(jsValue)\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\n/**\n * Checks if `node` is an alias for the 'tgpu' object, traditionally\n * available via `import tgpu from 'typegpu'`.\n */\nfunction isTgpu(ctx: Context, node: babel.Node | acorn.AnyNode): boolean {\n let path = '';\n\n let tail = node;\n while (true) {\n if (tail.type === 'MemberExpression') {\n if (\n (tail.property.type === 'Literal' ||\n tail.property.type === 'StringLiteral') &&\n tail.property.value === '~unstable'\n ) {\n // Bypassing the '~unstable' property.\n tail = tail.object;\n continue;\n }\n\n if (tail.property.type !== 'Identifier') {\n // Not handling computed expressions.\n break;\n }\n\n path = path ? `${tail.property.name}.${path}` : tail.property.name;\n tail = tail.object;\n } else if (tail.type === 'Identifier') {\n path = path ? `${tail.name}.${path}` : tail.name;\n break;\n } else {\n break;\n }\n }\n\n return ctx.tgpuAliases.has(path);\n}\n\nexport function gatherTgpuAliases(\n node: acorn.ImportDeclaration | babel.ImportDeclaration,\n ctx: Context,\n) {\n if (node.source.value === 'typegpu') {\n for (const spec of node.specifiers) {\n if (\n // The default export of 'typegpu' is the `tgpu` object.\n spec.type === 'ImportDefaultSpecifier' ||\n // Aliasing 'tgpu' while importing, e.g. import { tgpu as t } from 'typegpu';\n (spec.type === 'ImportSpecifier' &&\n spec.imported.type === 'Identifier' &&\n spec.imported.name === 'tgpu')\n ) {\n ctx.tgpuAliases.add(spec.local.name);\n } else if (spec.type === 'ImportNamespaceSpecifier') {\n // Importing everything, e.g. import * as t from 'typegpu';\n ctx.tgpuAliases.add(`${spec.local.name}.tgpu`);\n }\n }\n }\n}\n\nconst fnShellFunctionNames = ['fn', 'vertexFn', 'fragmentFn', 'computeFn'];\n\nexport function isShellImplementationCall(\n node: acorn.CallExpression | babel.CallExpression,\n ctx: Context,\n) {\n return (\n node.callee.type === 'CallExpression' &&\n node.callee.callee.type === 'MemberExpression' &&\n node.callee.callee.property.type === 'Identifier' &&\n fnShellFunctionNames.includes(node.callee.callee.property.name) &&\n node.arguments.length === 1 && isTgpu(ctx, node.callee.callee.object)\n );\n}\n\n/**\n * Extracts a name and expression from nodes that contain a label and an expression,\n * such as VariableDeclarator or PropertyDefinition.\n * Returns a tuple of [name, expression] if found, otherwise undefined.\n *\n * @example\n * extractLabelledExpression(node`let name = tgpu.bindGroupLayout({});`)\n * // [\"name\", node`tgpu.bindGroupLayout({})`]\n */\nfunction extractLabelledExpression<T extends acorn.AnyNode | babel.Node>(\n node: T,\n): [string, ExpressionFor<T>] | undefined {\n if (\n node.type === 'VariableDeclarator' &&\n node.id.type === 'Identifier' &&\n node.init\n ) {\n // let id = init;\n return [node.id.name, node.init as ExpressionFor<T>];\n } else if (node.type === 'AssignmentExpression') {\n // left = right;\n const maybeName = tryFindIdentifier(node.left);\n if (maybeName) {\n return [maybeName, node.right as ExpressionFor<T>];\n }\n } else if (\n (node.type === 'Property' || node.type === 'ObjectProperty') &&\n node.key.type === 'Identifier'\n ) {\n // const a = { key: value }\n return [node.key.name, node.value as ExpressionFor<T>];\n } else if (\n (node.type === 'ClassProperty' || node.type === 'PropertyDefinition') &&\n node.value &&\n node.key.type === 'Identifier'\n ) {\n // class Class {\n //\t key = value;\n // }\n return [node.key.name, node.value as ExpressionFor<T>];\n }\n}\n\nexport function getFunctionName(\n node: acorn.AnyNode | babel.Node,\n parent: acorn.AnyNode | babel.Node | null,\n): string | undefined {\n const maybeName = parent ? extractLabelledExpression(parent)?.[0] : undefined;\n return maybeName ??\n (node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression'\n ? node.id?.name\n : undefined);\n}\n\nconst resourceConstructors: string[] = [\n // tgpu\n 'bindGroupLayout',\n 'vertexLayout',\n 'privateVar',\n 'workgroupVar',\n 'const',\n 'slot',\n 'accessor',\n 'comptime',\n ...fnShellFunctionNames,\n // root\n 'createBuffer',\n 'createMutable',\n 'createReadonly',\n 'createUniform',\n 'createQuerySet',\n 'createPipeline',\n 'createComputePipeline',\n 'createGuardedComputePipeline',\n 'createRenderPipeline',\n 'createTexture',\n 'createSampler',\n 'createComparisonSampler',\n // d\n 'struct',\n 'unstruct',\n // other\n 'createView',\n];\n\n/**\n * Checks if `node` should be wrapped in an autoname function.\n * Since it is mostly for debugging and clean WGSL generation,\n * some false positives and false negatives are admissible.\n */\nfunction containsResourceConstructorCall(\n node: acorn.AnyNode | babel.Node,\n ctx: Context,\n) {\n if (node.type === 'CallExpression') {\n if (isShellImplementationCall(node, ctx)) {\n return true;\n }\n // struct({...})\n if (\n node.callee.type === 'Identifier' &&\n resourceConstructors.includes(node.callee.name)\n ) {\n return true;\n }\n if (node.callee.type === 'MemberExpression') {\n if (node.callee.property.type === 'Identifier') {\n // root.createBuffer({...})\n if (resourceConstructors.includes(node.callee.property.name)) {\n return true;\n }\n if (node.callee.property.name === '$name') {\n return false;\n }\n }\n // root.createBuffer(d.f32).$usage('storage')\n return containsResourceConstructorCall(node.callee.object, ctx);\n }\n }\n if (node.type === 'TaggedTemplateExpression') {\n return containsResourceConstructorCall(node.tag, ctx);\n }\n return false;\n}\n\n/**\n * Tries to find an identifier in a node.\n *\n * @example\n * // syntax is simplified, imagine the arguments are appropriate nodes instead\n * tryFindIdentifier('myBuffer'); // 'myBuffer'\n * tryFindIdentifier('buffers.myBuffer'); // 'myBuffer'\n * tryFindIdentifier('this.myBuffer'); // 'myBuffer'\n * tryFindIdentifier('[a, b]'); // undefined\n */\nfunction tryFindIdentifier(\n node: acorn.AnyNode | babel.Node,\n): string | undefined {\n if (node.type === 'Identifier') {\n return node.name;\n }\n if (node.type === 'PrivateName') {\n return tryFindIdentifier(node.id);\n }\n if (node.type === 'PrivateIdentifier') {\n return node.name;\n }\n if (node.type === 'MemberExpression') {\n return tryFindIdentifier(node.property);\n }\n}\n\ntype ExpressionFor<T extends acorn.AnyNode | babel.Node> = T extends\n acorn.AnyNode ? acorn.Expression : babel.Expression;\n\n/**\n * Checks if `node` contains a label and a tgpu expression that could be named.\n * If so, it calls the provided callback. Nodes selected for naming include:\n *\n * `let name = tgpu.bindGroupLayout({});` (VariableDeclarator)\n *\n * `name = tgpu.bindGroupLayout({});` (AssignmentExpression)\n *\n * `property: tgpu.bindGroupLayout({})` (Property/ObjectProperty)\n *\n * Since it is mostly for debugging and clean WGSL generation,\n * some false positives and false negatives are admissible.\n *\n * This function is NOT used for auto-naming shell-less functions.\n * Those are handled separately.\n *\n * @privateRemarks\n * When adding new checks, you need to call this method in the corresponding node in Babel.\n */\nexport function performExpressionNaming<T extends acorn.AnyNode | babel.Node>(\n ctx: Context,\n node: T,\n namingCallback: (node: ExpressionFor<T>, name: string) => void,\n) {\n if (!ctx.autoNamingEnabled) {\n return;\n }\n\n const labelledExpression = extractLabelledExpression(node);\n if (labelledExpression) {\n const [label, expression] = labelledExpression;\n if (containsResourceConstructorCall(expression, ctx)) {\n namingCallback(expression, label);\n }\n }\n}\n\nexport const useGpuDirective = 'use gpu';\n\n/** Regular expressions used for early pruning (to avoid unnecessary parsing, which is expensive) */\nexport const earlyPruneRegex = [/[\"']use gpu[\"']/, /t(ype)?gpu/];\n\nexport const operators = {\n '+': '__tsover_add',\n '-': '__tsover_sub',\n '*': '__tsover_mul',\n '/': '__tsover_div',\n '%': '__tsover_mod',\n '+=': '__tsover_add',\n '-=': '__tsover_sub',\n '*=': '__tsover_mul',\n '/=': '__tsover_div',\n '%=': '__tsover_mod',\n};\n","// Copied from https://github.com/unjs/unplugin/blob/f514bf8e2d751b48b3a5acb1077eb1292d9711b3/src/utils/filter.ts#L2\n// Used only in the babel version of the plugin, since others can rely on native unplugin functionality.\n\nimport { resolve } from 'pathe';\nimport picomatch from 'picomatch';\nimport type {\n Arrayable,\n Nullable,\n StringFilter,\n StringOrRegExp,\n} from 'unplugin';\n\nfunction toArray<T>(array?: Nullable<Arrayable<T>>): Array<T> {\n const result = array || [];\n if (Array.isArray(result)) return result;\n return [result];\n}\n\nconst BACKSLASH_REGEX = /\\\\/g;\nfunction normalize(path: string): string {\n return path.replace(BACKSLASH_REGEX, '/');\n}\n\nconst ABSOLUTE_PATH_REGEX = /^(?:\\/|(?:[A-Z]:)?[/\\\\|])/i;\nfunction isAbsolute(path: string): boolean {\n return ABSOLUTE_PATH_REGEX.test(path);\n}\n\nexport type PluginFilter = (input: string) => boolean;\nexport type TransformHookFilter = (id: string, code: string) => boolean;\n\ninterface NormalizedStringFilter {\n include?: StringOrRegExp[] | undefined;\n exclude?: StringOrRegExp[] | undefined;\n}\n\nfunction getMatcherString(glob: string, cwd: string) {\n if (glob.startsWith('**') || isAbsolute(glob)) {\n return normalize(glob);\n }\n\n const resolved = resolve(cwd, glob);\n return normalize(resolved);\n}\n\nfunction patternToIdFilter(pattern: StringOrRegExp): PluginFilter {\n if (pattern instanceof RegExp) {\n return (id: string) => {\n const normalizedId = normalize(id);\n const result = pattern.test(normalizedId);\n pattern.lastIndex = 0;\n return result;\n };\n }\n const cwd = process.cwd();\n const glob = getMatcherString(pattern, cwd);\n const matcher = picomatch(glob, { dot: true });\n return (id: string) => {\n const normalizedId = normalize(id);\n return matcher(normalizedId);\n };\n}\n\nfunction createFilter(\n exclude: PluginFilter[] | undefined,\n include: PluginFilter[] | undefined,\n): PluginFilter | undefined {\n if (!exclude && !include) {\n return;\n }\n\n return (input) => {\n if (exclude?.some((filter) => filter(input))) {\n return false;\n }\n if (include?.some((filter) => filter(input))) {\n return true;\n }\n return !(include && include.length > 0);\n };\n}\n\nfunction normalizeFilter(filter: StringFilter): NormalizedStringFilter {\n if (typeof filter === 'string' || filter instanceof RegExp) {\n return {\n include: [filter],\n };\n }\n if (Array.isArray(filter)) {\n return {\n include: filter,\n };\n }\n return {\n exclude: filter.exclude ? toArray(filter.exclude) : undefined,\n include: filter.include ? toArray(filter.include) : undefined,\n };\n}\n\nfunction createIdFilter(\n filter: StringFilter | undefined,\n): PluginFilter | undefined {\n if (!filter) return;\n const { exclude, include } = normalizeFilter(filter);\n const excludeFilter = exclude?.map(patternToIdFilter);\n const includeFilter = include?.map(patternToIdFilter);\n return createFilter(excludeFilter, includeFilter);\n}\n\nexport function createFilterForId(\n filter: StringFilter | undefined,\n): PluginFilter | undefined {\n const filterFunction = createIdFilter(filter);\n return filterFunction ? (id) => !!filterFunction(id) : undefined;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: ((k) => from[k]).bind(null, key),
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
+
value: mod,
|
|
24
|
+
enumerable: true
|
|
25
|
+
}) : target, mod));
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
let pathe = require("pathe");
|
|
29
|
+
let picomatch = require("picomatch");
|
|
30
|
+
picomatch = __toESM(picomatch);
|
|
31
|
+
|
|
32
|
+
//#region src/common.ts
|
|
33
|
+
const defaultOptions = {
|
|
34
|
+
include: /\.m?[jt]sx?(?:\?.*)?$/,
|
|
35
|
+
autoNamingEnabled: true,
|
|
36
|
+
earlyPruning: true
|
|
37
|
+
};
|
|
38
|
+
function embedJSON(jsValue) {
|
|
39
|
+
return JSON.stringify(jsValue).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Checks if `node` is an alias for the 'tgpu' object, traditionally
|
|
43
|
+
* available via `import tgpu from 'typegpu'`.
|
|
44
|
+
*/
|
|
45
|
+
function isTgpu(ctx, node) {
|
|
46
|
+
let path = "";
|
|
47
|
+
let tail = node;
|
|
48
|
+
while (true) if (tail.type === "MemberExpression") {
|
|
49
|
+
if ((tail.property.type === "Literal" || tail.property.type === "StringLiteral") && tail.property.value === "~unstable") {
|
|
50
|
+
tail = tail.object;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (tail.property.type !== "Identifier") break;
|
|
54
|
+
path = path ? `${tail.property.name}.${path}` : tail.property.name;
|
|
55
|
+
tail = tail.object;
|
|
56
|
+
} else if (tail.type === "Identifier") {
|
|
57
|
+
path = path ? `${tail.name}.${path}` : tail.name;
|
|
58
|
+
break;
|
|
59
|
+
} else break;
|
|
60
|
+
return ctx.tgpuAliases.has(path);
|
|
61
|
+
}
|
|
62
|
+
function gatherTgpuAliases(node, ctx) {
|
|
63
|
+
if (node.source.value === "typegpu") {
|
|
64
|
+
for (const spec of node.specifiers) if (spec.type === "ImportDefaultSpecifier" || spec.type === "ImportSpecifier" && spec.imported.type === "Identifier" && spec.imported.name === "tgpu") ctx.tgpuAliases.add(spec.local.name);
|
|
65
|
+
else if (spec.type === "ImportNamespaceSpecifier") ctx.tgpuAliases.add(`${spec.local.name}.tgpu`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const fnShellFunctionNames = [
|
|
69
|
+
"fn",
|
|
70
|
+
"vertexFn",
|
|
71
|
+
"fragmentFn",
|
|
72
|
+
"computeFn"
|
|
73
|
+
];
|
|
74
|
+
function isShellImplementationCall(node, ctx) {
|
|
75
|
+
return node.callee.type === "CallExpression" && node.callee.callee.type === "MemberExpression" && node.callee.callee.property.type === "Identifier" && fnShellFunctionNames.includes(node.callee.callee.property.name) && node.arguments.length === 1 && isTgpu(ctx, node.callee.callee.object);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Extracts a name and expression from nodes that contain a label and an expression,
|
|
79
|
+
* such as VariableDeclarator or PropertyDefinition.
|
|
80
|
+
* Returns a tuple of [name, expression] if found, otherwise undefined.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* extractLabelledExpression(node`let name = tgpu.bindGroupLayout({});`)
|
|
84
|
+
* // ["name", node`tgpu.bindGroupLayout({})`]
|
|
85
|
+
*/
|
|
86
|
+
function extractLabelledExpression(node) {
|
|
87
|
+
if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.init) return [node.id.name, node.init];
|
|
88
|
+
else if (node.type === "AssignmentExpression") {
|
|
89
|
+
const maybeName = tryFindIdentifier(node.left);
|
|
90
|
+
if (maybeName) return [maybeName, node.right];
|
|
91
|
+
} else if ((node.type === "Property" || node.type === "ObjectProperty") && node.key.type === "Identifier") return [node.key.name, node.value];
|
|
92
|
+
else if ((node.type === "ClassProperty" || node.type === "PropertyDefinition") && node.value && node.key.type === "Identifier") return [node.key.name, node.value];
|
|
93
|
+
}
|
|
94
|
+
function getFunctionName(node, parent) {
|
|
95
|
+
var _extractLabelledExpre, _node$id;
|
|
96
|
+
const maybeName = parent ? (_extractLabelledExpre = extractLabelledExpression(parent)) === null || _extractLabelledExpre === void 0 ? void 0 : _extractLabelledExpre[0] : void 0;
|
|
97
|
+
return maybeName !== null && maybeName !== void 0 ? maybeName : node.type === "FunctionDeclaration" || node.type === "FunctionExpression" ? (_node$id = node.id) === null || _node$id === void 0 ? void 0 : _node$id.name : void 0;
|
|
98
|
+
}
|
|
99
|
+
const resourceConstructors = [
|
|
100
|
+
"bindGroupLayout",
|
|
101
|
+
"vertexLayout",
|
|
102
|
+
"privateVar",
|
|
103
|
+
"workgroupVar",
|
|
104
|
+
"const",
|
|
105
|
+
"slot",
|
|
106
|
+
"accessor",
|
|
107
|
+
"comptime",
|
|
108
|
+
...fnShellFunctionNames,
|
|
109
|
+
"createBuffer",
|
|
110
|
+
"createMutable",
|
|
111
|
+
"createReadonly",
|
|
112
|
+
"createUniform",
|
|
113
|
+
"createQuerySet",
|
|
114
|
+
"createPipeline",
|
|
115
|
+
"createComputePipeline",
|
|
116
|
+
"createGuardedComputePipeline",
|
|
117
|
+
"createRenderPipeline",
|
|
118
|
+
"createTexture",
|
|
119
|
+
"createSampler",
|
|
120
|
+
"createComparisonSampler",
|
|
121
|
+
"struct",
|
|
122
|
+
"unstruct",
|
|
123
|
+
"createView"
|
|
124
|
+
];
|
|
125
|
+
/**
|
|
126
|
+
* Checks if `node` should be wrapped in an autoname function.
|
|
127
|
+
* Since it is mostly for debugging and clean WGSL generation,
|
|
128
|
+
* some false positives and false negatives are admissible.
|
|
129
|
+
*/
|
|
130
|
+
function containsResourceConstructorCall(node, ctx) {
|
|
131
|
+
if (node.type === "CallExpression") {
|
|
132
|
+
if (isShellImplementationCall(node, ctx)) return true;
|
|
133
|
+
if (node.callee.type === "Identifier" && resourceConstructors.includes(node.callee.name)) return true;
|
|
134
|
+
if (node.callee.type === "MemberExpression") {
|
|
135
|
+
if (node.callee.property.type === "Identifier") {
|
|
136
|
+
if (resourceConstructors.includes(node.callee.property.name)) return true;
|
|
137
|
+
if (node.callee.property.name === "$name") return false;
|
|
138
|
+
}
|
|
139
|
+
return containsResourceConstructorCall(node.callee.object, ctx);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (node.type === "TaggedTemplateExpression") return containsResourceConstructorCall(node.tag, ctx);
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Tries to find an identifier in a node.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* // syntax is simplified, imagine the arguments are appropriate nodes instead
|
|
150
|
+
* tryFindIdentifier('myBuffer'); // 'myBuffer'
|
|
151
|
+
* tryFindIdentifier('buffers.myBuffer'); // 'myBuffer'
|
|
152
|
+
* tryFindIdentifier('this.myBuffer'); // 'myBuffer'
|
|
153
|
+
* tryFindIdentifier('[a, b]'); // undefined
|
|
154
|
+
*/
|
|
155
|
+
function tryFindIdentifier(node) {
|
|
156
|
+
if (node.type === "Identifier") return node.name;
|
|
157
|
+
if (node.type === "PrivateName") return tryFindIdentifier(node.id);
|
|
158
|
+
if (node.type === "PrivateIdentifier") return node.name;
|
|
159
|
+
if (node.type === "MemberExpression") return tryFindIdentifier(node.property);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Checks if `node` contains a label and a tgpu expression that could be named.
|
|
163
|
+
* If so, it calls the provided callback. Nodes selected for naming include:
|
|
164
|
+
*
|
|
165
|
+
* `let name = tgpu.bindGroupLayout({});` (VariableDeclarator)
|
|
166
|
+
*
|
|
167
|
+
* `name = tgpu.bindGroupLayout({});` (AssignmentExpression)
|
|
168
|
+
*
|
|
169
|
+
* `property: tgpu.bindGroupLayout({})` (Property/ObjectProperty)
|
|
170
|
+
*
|
|
171
|
+
* Since it is mostly for debugging and clean WGSL generation,
|
|
172
|
+
* some false positives and false negatives are admissible.
|
|
173
|
+
*
|
|
174
|
+
* This function is NOT used for auto-naming shell-less functions.
|
|
175
|
+
* Those are handled separately.
|
|
176
|
+
*
|
|
177
|
+
* @privateRemarks
|
|
178
|
+
* When adding new checks, you need to call this method in the corresponding node in Babel.
|
|
179
|
+
*/
|
|
180
|
+
function performExpressionNaming(ctx, node, namingCallback) {
|
|
181
|
+
if (!ctx.autoNamingEnabled) return;
|
|
182
|
+
const labelledExpression = extractLabelledExpression(node);
|
|
183
|
+
if (labelledExpression) {
|
|
184
|
+
const [label, expression] = labelledExpression;
|
|
185
|
+
if (containsResourceConstructorCall(expression, ctx)) namingCallback(expression, label);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const useGpuDirective = "use gpu";
|
|
189
|
+
/** Regular expressions used for early pruning (to avoid unnecessary parsing, which is expensive) */
|
|
190
|
+
const earlyPruneRegex = [/["']use gpu["']/, /t(ype)?gpu/];
|
|
191
|
+
const operators = {
|
|
192
|
+
"+": "__tsover_add",
|
|
193
|
+
"-": "__tsover_sub",
|
|
194
|
+
"*": "__tsover_mul",
|
|
195
|
+
"/": "__tsover_div",
|
|
196
|
+
"%": "__tsover_mod",
|
|
197
|
+
"+=": "__tsover_add",
|
|
198
|
+
"-=": "__tsover_sub",
|
|
199
|
+
"*=": "__tsover_mul",
|
|
200
|
+
"/=": "__tsover_div",
|
|
201
|
+
"%=": "__tsover_mod"
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
//#endregion
|
|
205
|
+
//#region src/filter.ts
|
|
206
|
+
function toArray(array) {
|
|
207
|
+
const result = array || [];
|
|
208
|
+
if (Array.isArray(result)) return result;
|
|
209
|
+
return [result];
|
|
210
|
+
}
|
|
211
|
+
const BACKSLASH_REGEX = /\\/g;
|
|
212
|
+
function normalize(path) {
|
|
213
|
+
return path.replace(BACKSLASH_REGEX, "/");
|
|
214
|
+
}
|
|
215
|
+
const ABSOLUTE_PATH_REGEX = /^(?:\/|(?:[A-Z]:)?[/\\|])/i;
|
|
216
|
+
function isAbsolute(path) {
|
|
217
|
+
return ABSOLUTE_PATH_REGEX.test(path);
|
|
218
|
+
}
|
|
219
|
+
function getMatcherString(glob, cwd) {
|
|
220
|
+
if (glob.startsWith("**") || isAbsolute(glob)) return normalize(glob);
|
|
221
|
+
return normalize((0, pathe.resolve)(cwd, glob));
|
|
222
|
+
}
|
|
223
|
+
function patternToIdFilter(pattern) {
|
|
224
|
+
if (pattern instanceof RegExp) return (id) => {
|
|
225
|
+
const normalizedId = normalize(id);
|
|
226
|
+
const result = pattern.test(normalizedId);
|
|
227
|
+
pattern.lastIndex = 0;
|
|
228
|
+
return result;
|
|
229
|
+
};
|
|
230
|
+
const matcher = (0, picomatch.default)(getMatcherString(pattern, process.cwd()), { dot: true });
|
|
231
|
+
return (id) => {
|
|
232
|
+
return matcher(normalize(id));
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function createFilter(exclude, include) {
|
|
236
|
+
if (!exclude && !include) return;
|
|
237
|
+
return (input) => {
|
|
238
|
+
if (exclude === null || exclude === void 0 ? void 0 : exclude.some((filter) => filter(input))) return false;
|
|
239
|
+
if (include === null || include === void 0 ? void 0 : include.some((filter) => filter(input))) return true;
|
|
240
|
+
return !(include && include.length > 0);
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function normalizeFilter(filter) {
|
|
244
|
+
if (typeof filter === "string" || filter instanceof RegExp) return { include: [filter] };
|
|
245
|
+
if (Array.isArray(filter)) return { include: filter };
|
|
246
|
+
return {
|
|
247
|
+
exclude: filter.exclude ? toArray(filter.exclude) : void 0,
|
|
248
|
+
include: filter.include ? toArray(filter.include) : void 0
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function createIdFilter(filter) {
|
|
252
|
+
if (!filter) return;
|
|
253
|
+
const { exclude, include } = normalizeFilter(filter);
|
|
254
|
+
return createFilter(exclude === null || exclude === void 0 ? void 0 : exclude.map(patternToIdFilter), include === null || include === void 0 ? void 0 : include.map(patternToIdFilter));
|
|
255
|
+
}
|
|
256
|
+
function createFilterForId(filter) {
|
|
257
|
+
const filterFunction = createIdFilter(filter);
|
|
258
|
+
return filterFunction ? (id) => !!filterFunction(id) : void 0;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
//#endregion
|
|
262
|
+
Object.defineProperty(exports, '__toESM', {
|
|
263
|
+
enumerable: true,
|
|
264
|
+
get: function () {
|
|
265
|
+
return __toESM;
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
Object.defineProperty(exports, 'createFilterForId', {
|
|
269
|
+
enumerable: true,
|
|
270
|
+
get: function () {
|
|
271
|
+
return createFilterForId;
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
Object.defineProperty(exports, 'defaultOptions', {
|
|
275
|
+
enumerable: true,
|
|
276
|
+
get: function () {
|
|
277
|
+
return defaultOptions;
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
Object.defineProperty(exports, 'earlyPruneRegex', {
|
|
281
|
+
enumerable: true,
|
|
282
|
+
get: function () {
|
|
283
|
+
return earlyPruneRegex;
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
Object.defineProperty(exports, 'embedJSON', {
|
|
287
|
+
enumerable: true,
|
|
288
|
+
get: function () {
|
|
289
|
+
return embedJSON;
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
Object.defineProperty(exports, 'gatherTgpuAliases', {
|
|
293
|
+
enumerable: true,
|
|
294
|
+
get: function () {
|
|
295
|
+
return gatherTgpuAliases;
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
Object.defineProperty(exports, 'getFunctionName', {
|
|
299
|
+
enumerable: true,
|
|
300
|
+
get: function () {
|
|
301
|
+
return getFunctionName;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
Object.defineProperty(exports, 'isShellImplementationCall', {
|
|
305
|
+
enumerable: true,
|
|
306
|
+
get: function () {
|
|
307
|
+
return isShellImplementationCall;
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
Object.defineProperty(exports, 'operators', {
|
|
311
|
+
enumerable: true,
|
|
312
|
+
get: function () {
|
|
313
|
+
return operators;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
Object.defineProperty(exports, 'performExpressionNaming', {
|
|
317
|
+
enumerable: true,
|
|
318
|
+
get: function () {
|
|
319
|
+
return performExpressionNaming;
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
Object.defineProperty(exports, 'useGpuDirective', {
|
|
323
|
+
enumerable: true,
|
|
324
|
+
get: function () {
|
|
325
|
+
return useGpuDirective;
|
|
326
|
+
}
|
|
327
|
+
});
|