Skip to content

fix(parser): keep decorated private assignment targets as references - #217

Merged
vincentkoc merged 1 commit into
openclaw:mainfrom
SebTardif:claude/private-decorator-assign
Oct 31, 2026
Merged

vincentkoc merged 1 commit into
openclaw:mainfrom
SebTardif:claude/private-decorator-assign

Conversation

@SebTardif

Copy link
Copy Markdown

What does this PR do?

A decorated private member is taken out of the class. A plain write, this.#p = value, was already lowered to __privateSet. Compound assignment (+=, &&=, ||=, ??=), ++ and --, destructuring, and for (this.#p of/in ...) were left as a call, or as a #p name outside the class. Loading the file then throws SyntaxError: Left side of assignment is not a reference, or Cannot reference undeclared private names.

Those forms now lower to __privateWrapper(object, member, setter, getter)._. That property is a real assignment target: the getter reads the member and the setter writes it. A direct this.#p = value stays __privateSet. When = is a destructuring default ({ 0: this.#p = 1 }), the left side stays a reference, because a call cannot be a destructuring target. Only private names that the decorator lowering extracted are rewritten, so an undecorated #u in the same class still behaves as a private field.

A decorated private method reads back the method after the brand check. Passing the method itself as the getter would call it. A write still throws, because the storage is a WeakSet and has no setter.

Field initializers still go through __privateAdd, so an accessor decorator's setter does not run for the initializer. It runs for later assignments.

The runtime transpiler cache version is now 45, so output cached before this lowering is not reused.

This is the bug reported in oven-sh#47043. oven-sh#42651 is an open change for the same bug that expands this.#p += 1 into a get plus a set, and uses the wrapper only for other receivers.

How did you verify your code works?

USE_SYSTEM_BUN=1 bun test test/bundler/transpiler/private-decorator-assign.test.ts on Bun 1.4.4 fails with SyntaxError: Left side of assignment is not a reference at this.#p += 1.

bun run build:release test test/bundler/transpiler/private-decorator-assign.test.ts passes. The fixture is a .js file. The same source in a .ts file does not hit this bug, which is why the existing decorator suite did not catch it. The run covers plain assignment, compound and logical assignment (including short-circuit), prefix and postfix update, object and array destructuring, rest, defaults, for-of, for-in, a wrapping accessor, an undecorated private next to a decorated one, and a decorated private method.

bun run build:release test test/regression/issue/cyclic-imports-async-bundler.test.js passes. __privateWrapper is the last export in runtime.js, so the part indexes of __esm and __promiseAll do not move and that snapshot's debugId stays the same.

cargo check -p bun_ast -p bun_js_parser --offline --tests passes. The sorted runtime-import unit test does not link under a raw cargo test here, because that link does not pull in mimalloc.

bun bd cannot run on this machine. scripts/build/deps/webkit-artifacts.json has no macOS arm64 debug or asan WebKit tarball, so the debug build stops before compile.

A decorated private member is extracted from the class. Plain
assignment already became __privateSet. Compound assignment, update
operators, destructuring, and for-in/of heads were left as a call or
as a private name outside the class, so the engine threw SyntaxError.

Lower those forms to __privateWrapper(...)._, a property reference.
A direct assignment stays __privateSet. A decorated private method
still reads as the method and throws on write. Bump the runtime
transpiler cache so cached output from before this lowering is not
reused. The new helper is the last runtime.js export so existing
bundle debugId hashes stay the same.

Reported upstream as oven-sh/bun issue 47043.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
@vincentkoc
vincentkoc merged commit 7b573c0 into openclaw:main Oct 31, 2026
12 checks passed
vincentkoc added a commit that referenced this pull request Nov 1, 2026
* commit 'd9be087429c21e563bb5ac29f8a11805e64b56a3':
  fix(net): preserve TLS transport and completion ownership (#215)
  fix(parser): keep decorated private assignment targets as references (#217)

# Conflicts:
#	CHANGELOG.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants