Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Align WebKit and VM source-position assertions with Node's constructor locations and select these regressions for native stack-formatting changes in both fork CI lanes.

- Preserve the native-context count in the fast `v8.getHeapStatistics()` adapter and avoid appending a second strict code-generation flag to inherited worker arguments.

- Return one-based CallSite columns and null native positions, preserve column 1 in stack strings, and align constructor locations across stack formats and line breaks. Adapts [oven-sh/bun#35179](https://github.com/oven-sh/bun/pull/35179) and [oven-sh/bun#37396](https://github.com/oven-sh/bun/pull/37396). Thanks @robobun!
Expand Down
2 changes: 1 addition & 1 deletion docs/runtime/nodejs-compat.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The OpenClaw fork reports missing runtime imports without downloading npm packag

`Error.prepareStackTrace` supports deletion, descriptor restoration, and accessor replacement. Nested stack formatting and throwing formatters leave later captures usable.

`CallSite.getLineNumber()` and `getColumnNumber()` return one-based positions, or `null` when a frame has no source position. Stack strings include column 1 and use the same constructor positions as CallSites, including across line breaks. Some expression positions still differ from Node.js because JavaScriptCore and Bun's transpiler select different syntax locations.
`CallSite.getLineNumber()` and `getColumnNumber()` return one-based positions, or `null` when a frame has no source position. Stack strings include column 1 and use the same constructor positions as CallSites, pointing to the `new` keyword, including across line breaks and in `node:vm` scripts. Some expression positions still differ from Node.js because JavaScriptCore and Bun's transpiler select different syntax locations.

### [`node:assert`](https://nodejs.org/api/assert.html)

Expand Down
12 changes: 12 additions & 0 deletions scripts/openclaw-ci/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ const webkitSensitive = [
"test/js/node/module/node-module-module.test.js",
];

const sourcePositionSensitive = [
"test/js/bun/jsc/webkit-upgrade-7b485a76e9.test.ts",
"test/js/node/vm/vm-sourceUrl.test.ts",
];

// Runtime implementations span JS, Rust and C++; keep their shared boundaries explicit.
const sourceSuites: [RegExp, string[]][] = [
[/child_process|subprocess|spawn/i, ["child_process"]],
Expand Down Expand Up @@ -103,6 +108,13 @@ export function selectTests(changed: string[], tracked: string[], nightly: boole
}
}
} else if (path.startsWith("src/")) {
if (
/^src\/jsc\/bindings\/(?:CallSite\w*|ErrorStack\w*|FormatStackTraceForJS|ZigSourceProvider)\.(?:cpp|h)$/.test(
path,
)
) {
sourcePositionSensitive.forEach(test => selected.add(test));
}
for (const [pattern, suites] of sourceSuites) {
if (!pattern.test(path)) continue;
for (const test of [...smoke, ...broader]) {
Expand Down
15 changes: 15 additions & 0 deletions test/internal/source-lints/openclaw-ci.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,21 @@ test.each(["linux", "darwin"])("WebKit updates select VM, Intl, GC, hook and plu
expect(selected).not.toContain("test/bundler/esbuild/default.test.ts");
});

test.each(["linux", "darwin"])("stack position changes select WebKit and VM sourceURL coverage on %s", platform => {
for (const source of [
"CallSitePrototype.cpp",
"ErrorStackFrame.cpp",
"ErrorStackFrame.h",
"ErrorStackTrace.cpp",
"FormatStackTraceForJS.cpp",
"ZigSourceProvider.cpp",
]) {
const selected = selectTests([`src/jsc/bindings/${source}`], tracked, false, platform);
expect(selected).toContain("test/js/bun/jsc/webkit-upgrade-7b485a76e9.test.ts");
expect(selected).toContain("test/js/node/vm/vm-sourceUrl.test.ts");
}
});

test("changed tests are added exactly once, renamed tests use the new path, deleted tests are omitted", () => {
const added = "test/js/node/fs/new check.test.ts";
const deleted = "test/js/node/fs/removed.test.ts";
Expand Down
10 changes: 5 additions & 5 deletions test/js/bun/jsc/webkit-upgrade-7b485a76e9.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ describe("WebKit 7b485a76e9 upgrade", () => {
}
const frames = [...stack.matchAll(/positions\.js:(\d+):(\d+)/g)].map(m => [Number(m[1]), Number(m[2])]);
expect(frames).toEqual([
[6, 37],
[6, 28],
[4, 15],
[7, 6],
]);
Expand All @@ -164,8 +164,8 @@ describe("WebKit 7b485a76e9 upgrade", () => {
.at(-1);
}
};
expect(offsetFrames("throw new Error('first line')")).toEqual([11, 21]);
expect(offsetFrames("\nthrow new Error('second line')")).toEqual([12, 16]);
expect(offsetFrames("throw new Error('first line')")).toEqual([11, 12]);
expect(offsetFrames("\nthrow new Error('second line')")).toEqual([12, 7]);
});

test("an error from a class field initializer is reported where the constructor starts (c76c52f5b1)", () => {
Expand Down Expand Up @@ -205,7 +205,7 @@ describe("WebKit 7b485a76e9 upgrade", () => {
// That is not worth its cost to a short source, which is read if it is asked.
const short = (0, eval)("(function () {\n return new Error().stack;\n})");
expect(sourceHasLineStarts(short)).toBe(false);
expect(short()).toContain(":2:19");
expect(short()).toContain(":2:10");
expect(sourceHasLineStarts(short)).toBe(true);
// The builtins of the engine share one text, which is never parsed as a whole and needs no table.
expect(sourceHasLineStarts(Array.prototype.map)).toBe(false);
Expand All @@ -229,7 +229,7 @@ describe("WebKit 7b485a76e9 upgrade", () => {
if (length >= probe.length && (i % 3 === 1 || i % 64 <= 1 || i % 64 === 63 || i % 5 === 1)) {
const before = random(length - probe.length + 1);
text += fill(before, " ") + probe + fill(length - probe.length - before, " ") + end;
marks.push(`("p${i}")`);
marks.push(`new Error("p${i}")`);
} else text += (length >= 4 ? "/*" + fill(length - 4, "c") + "*/" : fill(length, " ")) + end;
}
text += "probes";
Expand Down
2 changes: 1 addition & 1 deletion test/js/node/vm/__snapshots__/vm-sourceUrl.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ throw new Error("hello");
^

Error: hello
at hellohello.js:2:16
at hellohello.js:2:7
at runInNewContext (unknown)
at <anonymous> (<this-url>:6:5)"
`;
Expand Down
Loading