Skip to content

Chakra napi shim: throws from class constructors are swallowed (don't surface to JS) #175

@bkaradzic-microsoft

Description

@bkaradzic-microsoft

On the Chakra backend, throwing a Napi::TypeError (or any Napi::Error) from a class constructor body — i.e. inside the function passed to Napi::ObjectWrap<T> / napi_define_class's callback — does not surface as a catchable JS exception. Instead the JS-side new MyClass() resolves to a half-constructed instance, so test code like expect(() => new (File as any)()).to.throw() silently fails.

This forces polyfills with required constructor arguments (WHATWG File, future Request, etc.) to either skip the WebIDL "missing required argument → TypeError" surface on Chakra, or omit the corresponding tests on Chakra.

Repro

class Foo : public Napi::ObjectWrap<Foo> {
public:
    static Napi::Function Init(Napi::Env env) {
        return DefineClass(env, "Foo", {});
    }
    Foo(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Foo>(info) {
        throw Napi::TypeError::New(info.Env(), "always throws");
    }
};

In JS on Chakra: expect(() => new Foo()).to.throw() fails — no exception is thrown.
On V8 and JSC: throws as expected.

Current workaround

In Polyfills/File/Tests/UnitTests/Scripts/tests.ts (introduced by #169), tests that assert the constructor throws on missing/invalid arguments are commented out with a TODO pointing here. They should be re-enabled atomically when this is fixed.

Likely root cause

The Chakra napi shim's ExternalCallback::Callback (in Core/Node-API/Source/js_native_api_chakra.cc) probably needs to translate env->last_exception into a JsRT exception via JsSetException before returning to the JsRT runtime when invoked in construct mode. The function-call path likely already does this; the constructor path appears not to.

Related

  • JsRH#172 (separate JSC napi shim quirk).
  • JsRH#169 (the PR that surfaced this).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions