addInitializer silently ignores a non-callable argument instead of throwing TypeError
Maintainers usually reply within 1 day
A pull request for this has already been merged.
- #1671 by @frostney — merged
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 82/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- javascript
- Domain
- compilers
Research direction
The check lives in TGocciaInitializerCollector.AddInitializer in source/units/Goccia.Evaluator.Decorators.pas, which both execution modes share. Read how it handles the first argument, then find where the codebase raises TypeErrors elsewhere so you raise one the same way. Done means all six cases in the issue throw a TypeError in both --mode=bytecode and --mode=interpreted, and regression cases are added to tests/language/decorators/add-initializer.js.
Written by the indexing model from the issue text.
Description
Summary
context.addInitializer(x) silently ignores a non-callable x (a number, string, object, undefined, or no argument) in both modes. The decorators proposal requires a TypeError.
Why
Decorators proposal (tc39/ecma262 PR #2417 at 59003ed6), CreateAddInitializerFunction (sec-createaddinitializerfunction), step 2 of the addInitializer closure:
If IsCallable(initializer) is false, throw a TypeError exception.
TGocciaInitializerCollector.AddInitializer (source/units/Goccia.Evaluator.Decorators.pas), which both modes use, only appends the value when it is callable, and otherwise returns undefined:
if (AArgs.Length > 0) and AArgs.GetElement(0).IsCallable then
begin
SetLength(FInitializers, Length(FInitializers) + 1);
FInitializers[High(FInitializers)] := AArgs.GetElement(0);
end;
Result := TGocciaUndefinedLiteralValue.UndefinedValue;
Current behavior
main at adabb564. Each of these prints no throw in both --mode=bytecode and --mode=interpreted:
const t = (label, f) => { try { f(); console.log(label, "no throw"); } catch (e) { console.log(label, e.constructor.name); } };
t("class", () => { const d = (c, ctx) => { ctx.addInitializer(42); }; @d class A {} });
t("method", () => { const d = (m, ctx) => { ctx.addInitializer("x"); }; class A { @d m() {} } });
t("field", () => { const d = (v, ctx) => { ctx.addInitializer({}); }; class A { @d x = 1; } });
t("static method", () => { const d = (m, ctx) => { ctx.addInitializer(undefined); }; class A { @d static m() {} } });
t("no argument", () => { const d = (c, ctx) => { ctx.addInitializer(); }; @d class A {} });
Decorators are not in Node.js 24, so there is no engine reference here; the expected behavior comes from the proposal text above.
Expected behavior
Each call throws a TypeError from addInitializer, which propagates out of the decorator and out of the class definition. This applies to every element kind, static and non-static, in both modes.
Scope notes
- The fix belongs in
TGocciaInitializerCollector.AddInitializer, and is the same change in both modes. - The step-1 sibling,
addInitializercalled after decoration has finished, is a use-after-free crash and is filed separately as #1667. - Add regression cases to
tests/language/decorators/add-initializer.js.
[!NOTE]
Created on behalf of @frostney using Claude Opus 5.5.
- Dominant language
- Pascal
- Stars
- 20
- Forks
- 6
- Avg merge
- 18h 43m
- Merged PRs (30d)
- 319
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from frostney/GocciaScript
-
internal
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
frostney/GocciaScript#1715 ·
Maintainers usually reply within 1 day
-
internal os specific
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
frostney/GocciaScript#1688 · 1 comment ·
Maintainers usually reply within 1 day
-
documentation
Difficulty 1/5 1-3 hours Newbie friendliness 84/100
frostney/GocciaScript#1510 ·
Maintainers usually reply within 1 day
-
documentation internal
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
frostney/GocciaScript#1271 ·
Maintainers usually reply within 1 day
-
internal
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
frostney/GocciaScript#1187 · 1 comment ·
Maintainers usually reply within 1 day
All issues in frostney/GocciaScript
Similar issues
-
area:codegen backend:cuda backend:hip bug direction:input
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
CrossGL/crosstl#3061 · 1 comment ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
build
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
AOMediaCodec/SVT-AV1#2500 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
rescript-lang/rescript#9037 ·
Maintainers usually reply within 1 day