Skip to content
Open
Show file tree
Hide file tree
Changes from 96 commits
Commits
Show all changes
115 commits
Select commit Hold shift + click to select a range
466c536
Add tests stub
aleksanderkatan Apr 28, 2026
4c88b76
Add more babel tests
aleksanderkatan Apr 28, 2026
7649af2
Update babel tests
aleksanderkatan Apr 28, 2026
6f47035
Add rollup tests
aleksanderkatan Apr 28, 2026
9605b2d
Keep ancestor chain in context in tinyest-for-wgsl
aleksanderkatan Apr 28, 2026
f4e1bab
Change externals from array to object
aleksanderkatan Apr 29, 2026
49e7596
Add addExternal function
aleksanderkatan Apr 29, 2026
beca358
Add a rudimentary implementation of external collection
aleksanderkatan Apr 29, 2026
4257b1d
Update bahbel externals generation
aleksanderkatan Apr 29, 2026
d6e4f7e
Update rollup
aleksanderkatan Apr 29, 2026
f11b111
Bump metadata version
aleksanderkatan May 28, 2026
9efa70c
Update remaining tests
aleksanderkatan May 28, 2026
5726bea
Split parsers.ts into three files
aleksanderkatan May 29, 2026
b6b2458
Clean up external addition in parsers.ts
aleksanderkatan May 29, 2026
57232ce
Add sanity tests for external prop access
aleksanderkatan May 29, 2026
d0db0fd
Revert externalNames to an array
aleksanderkatan May 29, 2026
6aeefe0
More tests
aleksanderkatan May 29, 2026
41276f7
Deduplicate Externals interface
aleksanderkatan Jun 8, 2026
cbc50bc
nits
aleksanderkatan Jun 8, 2026
c124e93
Merge remote-tracking branch 'origin/main' into feat/expand-property-…
aleksanderkatan Jun 8, 2026
c90f042
Review fixes
aleksanderkatan Jun 8, 2026
9bc7945
Wrap prop names in ""
aleksanderkatan Jun 8, 2026
2427b87
Add private prop autonaming tests
aleksanderkatan Jun 8, 2026
25b87a6
Autoname private properties
aleksanderkatan Jun 8, 2026
cc4e34e
Handle private property access
aleksanderkatan Jun 9, 2026
203e37c
Wrap prop names in "" in babel
aleksanderkatan Jun 9, 2026
d6808ca
Only wrap when necessary
aleksanderkatan Jun 9, 2026
1c36feb
Update tests
aleksanderkatan Jun 9, 2026
a1d7d12
Stop linting private property
aleksanderkatan Jun 9, 2026
c3b2b63
Review fix
aleksanderkatan Jun 9, 2026
d3bdf17
Merge branch 'main' into feat/expand-property-access-in-externals
aleksanderkatan Jun 9, 2026
5f578ef
Update parser
aleksanderkatan Jun 9, 2026
23b4f44
Collect externals from top in parsers and replace them in tinyest
aleksanderkatan Jun 10, 2026
8877ba1
Update unplugin and parsers tests
aleksanderkatan Jun 10, 2026
66a5090
broken test
aleksanderkatan Jun 12, 2026
669e47f
Remove setName from mergeExternals
aleksanderkatan Jun 16, 2026
692ac90
Name unnamed externals in propAccess and getById
aleksanderkatan Jun 16, 2026
a944c60
Limit tgpuDeclare to one external
aleksanderkatan Jun 16, 2026
754eb92
Remove unnecessary merge from tgpuResolve
aleksanderkatan Jun 16, 2026
a217940
Limit rawCodeSnippet to one $uses
aleksanderkatan Jun 16, 2026
1f8bccb
Add FnExternals, and throw if $uses is called multiple times
aleksanderkatan Jun 16, 2026
b0ec447
Prepare string-implemented functions for external swap
aleksanderkatan Jun 16, 2026
236075c
Finish replacing old externals with new externals && cleanup
aleksanderkatan Jun 19, 2026
7c7faad
More cleanup
aleksanderkatan Jun 19, 2026
a03b83f
Detect $uses on function with plugin metadata earlier
aleksanderkatan Jun 19, 2026
1a16a8b
Add FnExternals docs
aleksanderkatan Jun 19, 2026
9f33691
Add external name collision tests
aleksanderkatan Jun 19, 2026
052f36b
Add more tests & fix fragment out external
aleksanderkatan Jun 19, 2026
5ec7052
More tests && allow redundant external
aleksanderkatan Jun 19, 2026
54b8b27
Update docs
aleksanderkatan Jun 19, 2026
d7d48ae
Add compute tests
aleksanderkatan Jun 22, 2026
fc8b147
Move external tests to external.test.ts
aleksanderkatan Jun 22, 2026
cfb074a
Fix old external tests by tweaking the api
aleksanderkatan Jun 22, 2026
5b26ee6
nr fix
aleksanderkatan Jun 22, 2026
312f78d
Merge branch 'main' into fix/forbid-multiple-uses
aleksanderkatan Jun 22, 2026
29b0354
self-review fixes
aleksanderkatan Jun 22, 2026
bd481a7
Merge branch 'main' into feat/expand-property-access-in-externals
aleksanderkatan Jun 22, 2026
a06100f
Merge branch 'feat/flatten-externals' into feat/expand-property-acces…
aleksanderkatan Jun 22, 2026
638fe50
Update tests
aleksanderkatan Jun 22, 2026
56534b3
Simplify normalizeMetadataV2, update tests
aleksanderkatan Jun 22, 2026
5c7e23c
Simplify externals usage in plugins
aleksanderkatan Jun 22, 2026
59adaba
Optimize and document `tryFindExternalChain`
aleksanderkatan Jun 22, 2026
b84d942
Remove ancestor chain
aleksanderkatan Jun 22, 2026
2f38b37
Update tests
aleksanderkatan Jun 22, 2026
a3c5ad3
Update jsdoc
aleksanderkatan Jun 22, 2026
f9a4385
Fix multiple .$uses error
aleksanderkatan Jun 22, 2026
5d3386d
Allow externals to be undefined
aleksanderkatan Jun 22, 2026
83ee5b0
Fix external naming in wgslGenerator
aleksanderkatan Jun 22, 2026
7aaefbc
Merge branch 'fix/forbid-multiple-uses' into feat/expand-property-acc…
aleksanderkatan Jun 22, 2026
f8d8ed4
Update snapshots
aleksanderkatan Jun 22, 2026
c2a3141
Add a nested unnamed struct external test
aleksanderkatan Jun 26, 2026
d63d3bf
Merge remote-tracking branch 'origin/main' into feat/expand-property-…
aleksanderkatan Jun 26, 2026
ce0b389
Add some explaining the magic docs
aleksanderkatan Jun 26, 2026
45a3241
Add remaining docs
aleksanderkatan Jun 26, 2026
c6a3d52
Cut off flattening at '$'
aleksanderkatan Jun 26, 2026
2f75602
Update snapshots
aleksanderkatan Jun 26, 2026
d35ea36
Change externals array to set
aleksanderkatan Jun 26, 2026
37ed53e
Revert external undefined changes
aleksanderkatan Jun 26, 2026
953623e
Update external tests
aleksanderkatan Jun 26, 2026
1cd75cf
Review and update the doc
aleksanderkatan Jun 26, 2026
f30d344
Update snapshot
aleksanderkatan Jun 26, 2026
0a6b605
Update docs and tests
aleksanderkatan Jun 29, 2026
a9cb1f9
Review fixes
aleksanderkatan Jul 2, 2026
7fb2bb2
Merge remote-tracking branch 'origin/main' into feat/expand-property-…
aleksanderkatan Jul 2, 2026
2e94481
Self review
aleksanderkatan Jul 2, 2026
14ef463
Merge branch 'main' into feat/expand-property-access-in-externals
aleksanderkatan Jul 2, 2026
af80bcf
Apply suggestions from code review
aleksanderkatan Jul 6, 2026
5775d25
Remove externalNames
aleksanderkatan Jul 6, 2026
60d3a9c
Update snapshots
aleksanderkatan Jul 6, 2026
5ef3624
Remove redundant docs from shader-generation
aleksanderkatan Jul 6, 2026
1cfd5c4
Merge branch 'main' into feat/expand-property-access-in-externals
aleksanderkatan Jul 6, 2026
9628fa0
Move visited set onto context
aleksanderkatan Jul 7, 2026
6f0c43e
Merge branch 'main' into feat/expand-property-access-in-externals
aleksanderkatan Jul 7, 2026
18a30f4
Merge branch 'feat/expand-property-access-in-externals' into feat/pri…
aleksanderkatan Jul 7, 2026
1bfb85c
Merge fixes
aleksanderkatan Jul 7, 2026
9520237
Remove unreachable nodes
aleksanderkatan Jul 7, 2026
f09b819
Remove unused function
aleksanderkatan Jul 7, 2026
a5e96bc
Merge branch 'main' into feat/expand-property-access-in-externals
aleksanderkatan Jul 8, 2026
648dc26
Include the entire chain in autonamed externals
aleksanderkatan Jul 8, 2026
f492202
Apply suggestions from code review
aleksanderkatan Jul 8, 2026
58525a5
Merge branch 'main' into feat/expand-property-access-in-externals
aleksanderkatan Jul 8, 2026
f7b9498
Update packages/tinyest-for-wgsl/src/parsers.ts
aleksanderkatan Jul 9, 2026
191f7a0
Update apps/typegpu-docs/src/content/docs/advanced/explaining-the-mag…
aleksanderkatan Jul 9, 2026
1f3fc01
Kill spaces
aleksanderkatan Jul 9, 2026
7f22e3a
Update typegpu snapshots
aleksanderkatan Jul 9, 2026
dba4159
Only cache visited member expressions
aleksanderkatan Jul 9, 2026
defe487
Merge remote-tracking branch 'origin/main' into feat/expand-property-…
aleksanderkatan Jul 10, 2026
d743d93
Merge fixes
aleksanderkatan Jul 10, 2026
886759b
Merge remote-tracking branch 'origin/feat/expand-property-access-in-e…
aleksanderkatan Jul 10, 2026
4acec49
Review fix
aleksanderkatan Jul 10, 2026
4be9449
nr fix
aleksanderkatan Jul 10, 2026
afbddef
Merge remote-tracking branch 'origin/main' into feat/private-property…
aleksanderkatan Jul 13, 2026
15b6ec6
Merge fixes
aleksanderkatan Jul 13, 2026
a1c4c89
Merge branch 'main' into feat/private-property-access
aleksanderkatan Jul 13, 2026
bcd2ff0
Merge branch 'main' into feat/private-property-access
aleksanderkatan Jul 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/typegpu-docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ export default defineConfig({
slug: 'advanced/naming-convention',
badge: { text: 'dev', variant: 'note' },
},
DEV && {
label: 'Explaining the Magic',
slug: 'advanced/explaining-the-magic',
badge: { text: 'dev', variant: 'note' },
},
DEV && {
label: 'Shader Generation',
slug: 'advanced/shader-generation',
Expand Down
312 changes: 312 additions & 0 deletions apps/typegpu-docs/src/content/docs/advanced/explaining-the-magic.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,312 @@
---
title: Explaining the Magic
description: This doc explains how a 'use gpu' directive can make a function runnable on the GPU.
---

This tutorial explains in depth what exactly happens during the bundle time to make 'use gpu' functions possible.
Understanding this is not at all necessary to start using TypeGPU, but it may help contributors understand why some things work like they do.

## Introduction

Take a look at the following code. It declares a `counter` buffer, and increases it in `incrementPipeline`.

```ts twoslash
import { tgpu, d } from 'typegpu';

const root = await tgpu.init();

const counter = root.createMutable(d.vec2u);
const incrementBy = {
allModifier: tgpu.const(d.vec2u, d.vec2u(1, 1)),
yModifier: tgpu.const(d.u32, 2),
};

const increment = tgpu.computeFn({ workgroupSize: [1] })(() => {
'use gpu';
counter.$ += incrementBy.allModifier.$;
counter.$.y += incrementBy.yModifier.$;
});

const incrementPipeline = root.createComputePipeline({ compute: increment });

incrementPipeline.dispatchWorkgroups(1);
console.log(await counter.read()); // d.vec2u(1, 3)
```

TypeGPU translated this code to WebGPU, which can be previewed using `tgpu.resolve`:

```ts twoslash
import { tgpu } from 'typegpu';
const root = await tgpu.init();
const incrementPipeline = root.createComputePipeline({ compute: tgpu.computeFn({ workgroupSize: [1] })`` });
// ---cut---
console.log(tgpu.resolve([incrementPipeline]));
// @group(0) @binding(0) var<storage, read_write> counter: vec2u;
//
// const allModifier: vec2u = vec2u(1);
//
// const yModifier: u32 = 2u;
//
// @compute @workgroup_size(1) fn increment() {
// counter += allModifier;
// counter.y += yModifier;
// }
```

This was made possible by [unplugin-typegpu](/TypeGPU/tooling/unplugin-typegpu),
which modifies the existing code during bundle (build) time.
The modified code can be previewed for debug/educational purposes with the following trick:

```ts twoslash
// ... imports
const main = async () => {
// ... remaining file content
}
console.log(main.toString());
```

The code with the compute pipeline is transformed as follows (don't try to parse it, we will explain it on higher level in a second):

```js
async () => {
const root = await tgpu.init();
const counter = (/*#__PURE__*/(globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(root.createMutable(d.vec2u), "counter"));
const incrementBy = {
allModifier: (/*#__PURE__*/(globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(tgpu.const(d.vec2u, d.vec2u(1, 1)), "allModifier")),
yModifier: (/*#__PURE__*/(globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(tgpu.const(d.u32, 2), "yModifier"))
};
const increment = (/*#__PURE__*/(globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(tgpu.computeFn({ workgroupSize: [1] })((/*#__PURE__*/($ => (globalThis.__TYPEGPU_META__ ??= new WeakMap()).set($.f = (() => {
"use gpu";
counter.$ = __tsover_add(counter.$, incrementBy.allModifier.$);
counter.$.y = __tsover_add(counter.$.y, incrementBy.yModifier.$);
}), {
v: 2,
name: undefined,
ast: {"params":[],"body":[0,[[2,[7,"counter","$"],"+=",[7,"incrementBy.allModifier","$"]],[2,[7,[7,"counter","$"],"y"],"+=",[7,"incrementBy.yModifier","$"]]]]},
externals: { "counter": () => counter, "incrementBy.allModifier": () => incrementBy.allModifier, "incrementBy.yModifier": () => incrementBy.yModifier }
}) && $.f)({}))), "increment"));
const incrementPipeline = (/*#__PURE__*/(globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(root.createComputePipeline({ compute: increment }), "incrementPipeline"));
incrementPipeline.dispatchWorkgroups(1);
console.log(await counter.read());
}
```

As can be seen, unplugin heavily modifies code around some tgpu elements.
The changes can be split into three categories:

- auto-naming (`globalThis.__TYPEGPU_AUTONAME__`),
- function metadata assignment (`globalThis.__TYPEGPU_META__`),
- operator overloading (`__tsover_add` and similar).

## Auto-naming

Most TypeGPU resources can be named via the `$name` method.
While this is completely optional, a name can make debugging easier, and it also serves as a primer for identifiers in resulting WGSL.

`unplugin-typegpu` traverses the AST of each bundled file, and matches most common patterns where a default name for a resource (recognized by constructor name) can be inferred.

```js
const counter = root.createMutable(d.vec2u); // can be named 'counter'

const incrementBy = {
allModifier: tgpu.const(d.vec2u, d.vec2u(1, 1)), // can be named 'allModifier'
}
```

The matched resource is only wrapped in the autonaming function if the method `$name` was not called before:

```ts
const main = () => {
const myConst = tgpu.const(d.u32, 2).$name('incrementValue');
const otherConst = tgpu.const(d.u32, 2);
};

console.log(main.toString());
// () => {
// const myConst = tgpu.const(d.u32, 2).$name("incrementValue");
// const otherConst = (/*#__PURE__*/(globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(tgpu.const(d.u32, 2), "otherConst"));
// }
```

The `globalThis.__TYPEGPU_AUTONAME__` function checks its argument for the `$internal` symbol and `$name` prop, and if both are present (and the item does not already have a name), calls `$name` on the item.
Therefore, some potential false positive calls to `__TYPEGPU_AUTONAME__` (e.g. if user named their unrelated function `createMutable`) cause no harm.

It is worth noting that we actually wrap the function in a `(globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))` call:
we cannot know for sure that TypeGPU was already imported and assigned the autonaming function, so we need a fallback.
This is also the reason why we cannot just export a function like `tgpu.name`.

:::note
Not all resources can be named by the unplugin.
The most popular case where a name is not assigned is when a resource is returned from a function.
Such resources are named 'item' in the resolved WGSL.
```ts
const createBuffer = () => {
return root.createBuffer(d.u32);
}
```
:::


## Function metadata assignment

Function metadata is what makes it possible to generate WGSL from JavaScript code.
The metadata consists of the metadata version, the function name, the AST ([abstract syntax tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree)), and externals (the captured scope of the function),
Only functions marked with `'use gpu'` are processed, as well as those immediately passed into `tgpu.fn` shells.

### AST

The plugin uses the [tinyest-for-wgsl](https://github.com/software-mansion/TypeGPU/blob/main/packages/tinyest-for-wgsl/README.md)
package to parse the function AST into our custom AST format called [tinyest](https://github.com/software-mansion/TypeGPU/blob/main/packages/tinyest/README.md).
Our `wgslGenerator` traverses this AST and generates code snippets.

This could theoretically be done at runtime from the function's `toString`, but it would require bundling a JavaScript parser with TypeGPU, and make catching externals impossible.

### Externals

Along with AST, [tinyest-for-wgsl](https://github.com/software-mansion/TypeGPU/blob/main/packages/tinyest-for-wgsl/README.md) also returns a set of externals (variables captured from outer scope).
This section is more technical to explain our design choices.

#### Step 1: tinyest-for-wgsl

During tinyest generation, tinyest-for-wgsl also remembers all variables introduced into the scope. This lets it return a set of variables that reference outer scope.
Externals are immediately flattened, which means that the prop accesses are 'squashed' into identifiers:

```ts
const fn = () => {
'use gpu';
const a = 1; // no externals introduced
const b = a + 1; // no externals introduced
const c = ext; // 'ext' added to externals
const d = ext.p; // 'ext.p' added to externals, the prop access is replaced with an identifier 'ext.p'
}
// tinyest-for-wgsl returns the generated AST and externals: Set { 'ext', 'ext.p' }
// No code was modified so far, the prop access squashing only applies to the generated AST.
```

The externals are not flattened all the way to the end though. There are three most important cases where we stop early:

```ts
const fn = () => {
'use gpu';
const a = ext.p1.p2().p3; // 'ext.p1.p2' added to externals
const b = ext.q1['q2'].q3; // 'ext.q1' added to externals
const c = ext.r1.$.r3; // 'ext.r1' added to externals
}
```

Stopping at `$` is not necessary in any way for the library to function properly.
However, this lets the library try to auto-name resources that were missed by unplugin autonaming,
while also not affecting the tree-shaking.

#### Step 2: assigning metadata

When the unplugin assigns metadata, the list of externals is turned into an object of thunks:
```ts
const externals = {
"ext.p1.p2": () => ext.p1.p2,
"ext.q1": () => ext.q1,
"ext.r1": () => ext.r1
}
```

There are two important reasons why we need to delay the external computation and cannot just generate entries like `"ext.p1.p2": ext.p1.p2`.

The first reason is externals recapture:
```ts
let buffer;
let pipeline;
const computeFn = tgpu.computeFn({ workgroupSize: [1] })(() => {
'use gpu'; buffer.$ += 1;
}); // { buffer: buffer } would now become { buffer: undefined }
buffer = root.createMutable(d.u32); // externals do not update
```
The same scenario may occur when a function references resources that are recreated (e.g. a resized buffer).

The second reason is the fact that some of our getters depend on the current resolution mode.
`const.$` returns the value of the const when called outside of resolution, but during resolution it returns a different object with `[$ownSnippet]` and `[$resolve]` symbols.

#### Step 3: runtime

At runtime, the thunks are changed to getters for convenience.

```ts
const externals = {
get "ext.p1.p2"() { return ext.p1.p2 },
get "ext.q1"() { return ext.q1 },
get "ext.r1"() { return ext.r1 }
}
```

This iteration of externals is still shared between different resolutions of the same function, thus we cannot concretize the externals just yet.

Also, during resolution, deciding whether a given object comes from externals is difficult. Getters let us forget about this problem.
Without this change, the `wgslGenerator` would throw when encountering a function not marked with 'use gpu'.

When the `wgslGenerator` cannot find an identifier in scope,
it accesses the externals, which return the correct code snippets and automatically add any used definitions to the context,
as this is the behavior of resource prop access during resolution.

:::caution[Fragility of external prop access]
There are cases where external prop access performed in during resolution modifies the context.

The following code assumes that `helperAccess.$` is actually called in our internals.
This may happen for example if we included the entire prop chain in externals,
and then iterated over external values during resolution.

```ts
const helper = () => {
'use gpu';
return 2;
};
const helperAccess = tgpu.accessor(d.u32, helper);

const main = () => {
'use gpu';
if (2 + 2 === 5) {
return helperAccess.$;
}
return 0;
};

// This snippet would generate if `resolve` actually executed `helperAccess.$`.
expect(tgpu.resolve([main])).toMatchInlineSnapshot(`
"fn helper() -> i32 {
return 2;
}

fn main() -> i32 {
return 0;
}"
`);
```

This situation can occur even when pruning externals at `.$`:
```ts
const ctx = {
get helper() {
return helperAccess.$;
},
};

// ctx.helper
```

This is the reason why in unplugin we prepend each external with `() =>`
instead of just prepending the entire object - this lets us only evaluate the externals that were actually used.

:::

## Operator overloading

To allow [tsover](https://github.com/software-mansion/tsover/tree/main) to work as we expect when the function is called in JavaScript, operators used inside the function body are swapped with calls to functions like `__tsover_add`, defined by [tsover-runtime](https://github.com/software-mansion/tsover/blob/main/packages/tsover-runtime/README.md).
This makes it possible to add vectors together without referencing `std.mul` and such.

:::note
This change occurs only in the actual code.
Generated tinyest metadata is not modified.
:::

:::caution
`unplugin-typegpu` only transforms operators inside of 'use gpu' functions.
:::

47 changes: 0 additions & 47 deletions apps/typegpu-docs/src/content/docs/advanced/shader-generation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,53 +39,6 @@ const boid = createBoid();
// ^?
```

:::caution
We could do everything at runtime, transforming the code a bit so that the TypeGPU shader generator can have access to
a function's JS source code, along with references to values referenced from the outer scope.

The code shipped to the browser could look like so:
```js
const createBoid = () => {
'use gpu';
return Boid({ pos: vec3(), vel: vec3(0, 1, 0) });
};

// Associate metadata with the function, which the TypeGPU generator can later use
(globalThis.__TYPEGPU_META__ ??= new WeakMap()).set(createBoid, {
v: 1,
name: 'createBoid',
code: `() => {
'use gpu';
return Boid({ pos: vec3(), vel: vec3(0, 1, 0) });
}`,
get externals() { return { Boid, vec3 }; },
});
```

However, parsing code at runtime requires both shipping the parser to the end user, and having to spend time parsing the code,
sacrificing load times and performance.
:::

In order to avoid parsing at runtime while keeping the desired flexibility, we parse the AST at build time and compress it into
our custom format called [tinyest](https://npmjs.com/package/tinyest). It retains only information required for WGSL code
generation.

The code shipped to the browser looks more like this:
```js
const createBoid = () => {
'use gpu';
return Boid({ pos: vec3(), vel: vec3(0, 1, 0) });
};

(globalThis.__TYPEGPU_META__ ??= new WeakMap()).set(createBoid, {
v: 1,
name: 'createBoid',
// NOTE: Not meant to be read by humans
ast: {params:[],body:[0,[[10,[6,"Boid",[[104,{pos:[6,"vec3",[]],vel:[6,"vec3",[[5,"0"],[5,"1"],[5,"0"]]]}]]]]]],externalNames:["Boid","vec3"]},
get externals() { return { Boid, vec3 }; },
});
```

## Snippets

Snippets are the basis for TypeGPU shader code generation. They are immutable objects that hold three values:
Expand Down
7 changes: 0 additions & 7 deletions packages/eslint-plugin/src/rules/noUnsupportedSyntax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,6 @@ export const noUnsupportedSyntax = createRule({
report(node, `'new' expression`);
},

PrivateIdentifier(node) {
if (!directives.getEnclosingTypegpuFunction()) {
return;
}
report(node, 'private identifier');
},

Property(node) {
if (!directives.getEnclosingTypegpuFunction()) {
return;
Expand Down
Loading
Loading