Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
2 changes: 1 addition & 1 deletion scripts/build/deps/webkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* for local mode. Override via `--webkit-version=<hash>` to test a branch.
* From https://github.com/oven-sh/WebKit releases.
*/
export const WEBKIT_VERSION = "cf1b36ec8703d8e87436094d21d478d358c7d886";
export const WEBKIT_VERSION = "autobuild-preview-pr-650-13bd3c9b";
Comment thread
robobun marked this conversation as resolved.
Resolved
Comment thread
robobun marked this conversation as resolved.
Resolved

/**
* WebKit (JavaScriptCore) — the JS engine.
Expand Down
59 changes: 59 additions & 0 deletions test/bundler/transpiler/runtime-transpiler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,62 @@ describe("unterminated string literals in large files", () => {
expect(exitCode).toBe(1);
});
});

test("the call of a parenthesized optional chain is not part of the chain", async () => {
// `(a?.b as F)()` and `(a?.b)!()` print as `(a?.b)()`. The parentheses end the optional chain, so a nullish `a`
// makes the call throw after the arguments ran. A present `a` is the `this` of the call, also in a class field.
using dir = tempDir("transpiler-parenthesized-optional-chain-call", {
"index.ts": `
type Fn = (this: unknown, ...args: unknown[]) => unknown;
const present: { fn?: Fn } | undefined = {
fn() {
return this === present ? "called" : "wrong this";
},
};
const missing = undefined as { fn?: Fn } | undefined;
const outcome = (run: () => unknown) => {
try {
return String(run());
} catch (e) {
return (e as Error).constructor.name;
}
};
class Fields {
cast = (present?.fn as Fn)();
nonNull = (present?.fn)!();
static cast = (present?.fn as Fn)();
}
const fields = new Fields();
let argumentsEvaluated = 0;
console.log(
JSON.stringify({
fields: [fields.cast, fields.nonNull, Fields.cast],
present: [(present?.fn as Fn)(), (present?.fn)!()],
missing: [outcome(() => (missing?.fn as Fn)()), outcome(() => (missing?.fn)!(argumentsEvaluated++))],
argumentsEvaluated,
oneChain: [outcome(() => missing?.fn!()), outcome(() => (missing?.fn)?.())],
}),
);
`,
});

await using proc = Bun.spawn({
cmd: [bunExe(), "index.ts"],
env: bunEnv,
cwd: String(dir),
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
stdout: "pipe",
stderr: "pipe",
});

const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);

expect(stderr).toBe("");
expect(JSON.parse(stdout)).toEqual({
fields: ["called", "called", "called"],
present: ["called", "called"],
missing: ["TypeError", "TypeError"],
argumentsEvaluated: 1,
oneChain: ["undefined", "undefined"],
});
expect(exitCode).toBe(0);
});
Loading
Loading