diff --git a/src/node.cc b/src/node.cc index 6f946ab3ad1cc7..494dfcf4eec2f7 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2290,6 +2290,13 @@ static void DLOpen(const FunctionCallbackInfo& args) { // -1 is used for N-API modules if ((mp->nm_version != -1) && (mp->nm_version != NODE_MODULE_VERSION)) { + // Even if the module did self-register, it may have done so with the wrong + // version. We must only give up after having checked to see if it has an + // appropriate initializer callback. + if (auto callback = GetInitializerCallback(&dlib)) { + callback(exports, module, context); + return; + } char errmsg[1024]; snprintf(errmsg, sizeof(errmsg), diff --git a/test/addons/hello-world/binding.cc b/test/addons/hello-world/binding.cc index ba6a22d7196d26..e267a3b2a7629a 100644 --- a/test/addons/hello-world/binding.cc +++ b/test/addons/hello-world/binding.cc @@ -15,3 +15,20 @@ extern "C" NODE_MODULE_EXPORT void INITIALIZER(v8::Local exports, v8::Local context) { NODE_SET_METHOD(exports, "hello", Method); } + +static void FakeInit(v8::Local exports, + v8::Local module, + v8::Local context) { + auto isolate = context->GetIsolate(); + auto exception = v8::Exception::Error(v8::String::NewFromUtf8(isolate, + "FakeInit should never run!", v8::NewStringType::kNormal) + .ToLocalChecked()); + isolate->ThrowException(exception); +} + +// Define a Node.js module, but with the wrong version. Node.js should still be +// able to load this module, multiple times even, because it exposes the +// specially named initializer above. +#undef NODE_MODULE_VERSION +#define NODE_MODULE_VERSION 3 +NODE_MODULE(NODE_GYP_MODULE_NAME, FakeInit)