Skip to content

Report "not a constructor" for a non-object new target - #1655

Open
andreasrosdal wants to merge 3 commits into
quickjs-ng:masterfrom
nordstjernen-web:fix-not-a-constructor-message
Open

Report "not a constructor" for a non-object new target#1655
andreasrosdal wants to merge 3 commits into
quickjs-ng:masterfrom
nordstjernen-web:fix-not-a-constructor-message

Conversation

@andreasrosdal

Copy link
Copy Markdown
Contributor

JS_CallConstructorInternal() is only reached from a new-expression, but two of its three failure paths throw not a function: a non-object callee, and an object whose class has no call handler. Only the !is_constructor case gets the right message.

new (1);           // TypeError: not a function
new (undefined);   // TypeError: not a function

V8 says 1 is not a constructor and undefined is not a constructor. Route both paths through JS_ThrowTypeErrorNotAConstructor(); the not_a_function label goes with them.

🤖 Generated with Claude Code

https://claude.ai/code/session_014mv33YvfHz7t9mmkituBnn


Generated by Claude Code

claude and others added 3 commits August 6, 2026 18:14
JS_CallConstructorInternal() is only reached from a new-expression, but two
of its three failure paths throw "not a function": a non-object callee, and
an object whose class has no call handler. Only the !is_constructor case
gets the right message.

    new (1);           // TypeError: not a function
    new (undefined);   // TypeError: not a function

V8 says "1 is not a constructor" and "undefined is not a constructor" for
these. Route both paths through JS_ThrowTypeErrorNotAConstructor(); the
not_a_function label goes with them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014mv33YvfHz7t9mmkituBnn
The JS test covers `new x` and Reflect.construct() over every primitive
type, keeps the named-function form of the message pinned, and checks that
*calling* a non-callable still reports "not a function".

The api-test covers the one path that JS cannot reach: an object whose
class has no call handler but which carries the constructor bit, set
through JS_SetConstructorBit().

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6eRbuuuCujKgQkrHgvMrc
The message now depends only on whether the target is a constructor, so
the interesting cases are the things that are callable but still are not:
generators, async generators, method shorthand, accessors, class and
static methods, a bound arrow or method, and a proxy of any of them, each
as new, as Reflect.construct and as new.target -- against the shapes that
do construct. Also a revoked proxy, which reports being revoked rather than
not being a constructor, and super() reaching a non-constructor parent.
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