Skip to content
Open
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: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ Custom event loop implementation for Bun's runtime requirements
```

### When a test fails, and after an upstream sync
`JSTests/`, `LayoutTests/js` and the PerformanceTests collections are upstream's tests, and this fork has changed 120 of them. `JSTests/BUN-TEST-DIFFERENCES.md` lists every one by reason: the behaviors the fork has on purpose (with the fork code behind each and the files whose expectations follow it), the tests narrowed to the modes or builds they can pass in, and the ones skipped with `TODO(bun)` for a known gap. Read it before changing a test's expectation or skipping one: a failure that matches an entry there means the test is what to change; one that matches none is a regression in the engine. Its last section is the procedure for sorting a new failure. When a test is changed, add it to that file, and put a `// Bun:` or `// TODO(bun):` comment on the changed line saying what upstream expects. `JSTests/CLAUDE.md` and `JSTests/README.md` are upstream's files: leave them as they are.
`JSTests/`, `LayoutTests/js` and the PerformanceTests collections are upstream's tests, and this fork has changed 122 of them. `JSTests/BUN-TEST-DIFFERENCES.md` lists every one by reason: the behaviors the fork has on purpose (with the fork code behind each and the files whose expectations follow it), the tests narrowed to the modes or builds they can pass in, and the ones skipped with `TODO(bun)` for a known gap. Read it before changing a test's expectation or skipping one: a failure that matches an entry there means the test is what to change; one that matches none is a regression in the engine. Its last section is the procedure for sorting a new failure. When a test is changed, add it to that file, and put a `// Bun:` or `// TODO(bun):` comment on the changed line saying what upstream expects. `JSTests/CLAUDE.md` and `JSTests/README.md` are upstream's files: leave them as they are.

## Development Tips

Expand Down
23 changes: 20 additions & 3 deletions JSTests/BUN-TEST-DIFFERENCES.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Where this fork's tests differ from upstream's, and why

`JSTests/`, `LayoutTests/js` and the PerformanceTests collections are upstream's tests. This fork changes 120 of them and
`JSTests/`, `LayoutTests/js` and the PerformanceTests collections are upstream's tests. This fork changes 122 of them and
three runner scripts. Every change is listed here by the reason for it, so that after an upstream sync a failing test can
be sorted into one of three piles:

1. **The fork behaves differently on purpose.** Update the expectation. Sections A1–A9 list every such behavior, how to
1. **The fork behaves differently on purpose.** Update the expectation. Sections A1–A10 list every such behavior, how to
recognize it in a failure, and the fork code that causes it. If a failure matches one of these and the fork code is
still there, the test is the thing to change.
2. **The test cannot pass in a mode or build we run.** Skip it in that mode only, with the reason. Section B.
Expand Down Expand Up @@ -113,6 +113,23 @@ Rules for an edit to an upstream test:
- Fork code: `DecoderStringTable::jsStringFor` (`runtime/CachedTypes.h:132`): loading a cache interns nothing.
- File: `stress/jsstring-definitely-atom-bit.js`: `$skipModes << "bytecode-cache"`. The other modes run it unchanged.

### A10. With parameter expressions, a `var arguments` in the body is a binding of its own

- Upstream keeps one `arguments` binding, in the parameter scope. A store to the body's `var arguments` changes what the
parameter expressions and their closures read. A function named `arguments` in a block of the body is stored to that
same binding when the block runs.
- Fork code: the `FunctionNode` constructor of `BytecodeGenerator` (`bytecompiler/BytecodeGenerator.cpp`). Its loop over
`varDeclarations()` creates the var `arguments` like any other var; upstream skips it when
`shouldCreateArgumentsVariableInParameterScope` is set. `initializeDefaultParameterValuesAndSetupFunctionScopeStack`
then copies the parameter scope's value into the var, as it does for a var that has a parameter's name.
`hoistSloppyModeFunctionIfNecessary` always finds the var; upstream falls back to the parameter scope.
- For `var arguments` this is FunctionDeclarationInstantiation step 28. For the function in a block it is what V8 does
and what https://github.com/tc39/ecma262/issues/991 proposes: the var exists from the start. The current text of
Annex B.3.2.1 makes that var when the block runs, which only a store before the block or a `delete` after it can see.
- Recognize: in `function foo(x = () => arguments) { var arguments = 25; }`, `x()` is the arguments object. Upstream: 25.
- Files (2), one expectation each: `stress/arrow-functions-as-default-parameter-values.js`,
`stress/sloppy-mode-hoist-arguments-function-non-simple-parameter-list.js`.

---

## B. The test cannot pass in a mode or build we run: narrowed, not changed
Expand Down Expand Up @@ -154,7 +171,7 @@ Rules for an edit to an upstream test:

## E. After a sync: a failing test, step by step

1. Does the difference match A1–A9 exactly (same text, same shape)? Check that the fork code named there is still in the
1. Does the difference match A1–A10 exactly (same text, same shape)? Check that the fork code named there is still in the
tree, then update the expectation with a `// Bun:` comment and add the file to its list here.
2. Does it fail only in one mode or only with ASan, for a reason in the test and not the engine (it counts JIT compiles,
depends on allocation never failing, needs more than 300 s)? Narrow it as in B.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ test(function() {
test(function() {
function foo(x = ()=>arguments) {
var arguments = 25;
assert(x() === arguments);
// Bun: upstream expects x() === arguments. The body's var is a binding of its own (FunctionDeclarationInstantiation step 28), as in V8.
assert(x() !== arguments);
assert(x().length === 1);
assert(arguments === 25);
}
foo(undefined);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ function assert(b) {
}
}
assert(z !== originalArguments);
assert(x() === z);
// Bun: upstream expects x() === z. The function goes to the body's var (Annex B.3.2.1 stores to the VariableEnvironment), as in V8. The closure in the parameters keeps the arguments object.
assert(x() === originalArguments);
assert(arguments === z);
assert(typeof z === "function");
assert(z() === 25);
}());
Expand Down
Loading
Loading