Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
n-api: update napi_wrap error behavior
Browse files Browse the repository at this point in the history
The `napi_wrap` function is expected to return an error if a wrapped
object is passed to it. A given object can only be wrapped once.

PR-URL: #336
Reviewed-By: Kunal Pathak <kunal.pathak@microsoft.com>
  • Loading branch information
kfarnung committed Jul 20, 2017
1 parent cbfb520 commit 9ab193b
Showing 1 changed file with 32 additions and 12 deletions.
44 changes: 32 additions & 12 deletions src/node_api_jsrt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,31 @@ JsNameValueFromPropertyDescriptor(const napi_property_descriptor* p,
}
return napi_ok;
}

inline napi_status FindWrapper(JsValueRef obj, JsValueRef* result) {
// Search the object's prototype chain for the wrapper with external data.
// Usually the wrapper would be the first in the chain, but it is OK for
// other objects to be inserted in the prototype chain.
JsValueRef wrapper = obj;
bool hasExternalData = false;

JsValueRef nullValue = JS_INVALID_REFERENCE;
CHECK_JSRT(JsGetNullValue(&nullValue));

do {
CHECK_JSRT(JsGetPrototype(wrapper, &wrapper));
if (wrapper == JS_INVALID_REFERENCE || wrapper == nullValue) {
*result = JS_INVALID_REFERENCE;
return napi_ok;
}

CHECK_JSRT(JsHasExternalData(wrapper, &hasExternalData));
} while (!hasExternalData);

*result = wrapper;
return napi_ok;
}

} // end of namespace jsrtimpl

// Intercepts the Node-V8 module registration callback. Converts parameters
Expand Down Expand Up @@ -1351,6 +1376,10 @@ napi_status napi_wrap(napi_env env,
napi_ref* result) {
JsValueRef value = reinterpret_cast<JsValueRef>(js_object);

JsValueRef wrapper = JS_INVALID_REFERENCE;
CHECK_NAPI(jsrtimpl::FindWrapper(value, &wrapper));
RETURN_STATUS_IF_FALSE(wrapper == JS_INVALID_REFERENCE, napi_invalid_arg);

jsrtimpl::ExternalData* externalData = new jsrtimpl::ExternalData(
env, native_object, finalize_cb, finalize_hint);
if (externalData == nullptr) return napi_set_last_error(napi_generic_failure);
Expand All @@ -1376,18 +1405,9 @@ napi_status napi_wrap(napi_env env,
napi_status napi_unwrap(napi_env env, napi_value js_object, void** result) {
JsValueRef value = reinterpret_cast<JsValueRef>(js_object);

// Search the object's prototype chain for the wrapper with external data.
// Usually the wrapper would be the first in the chain, but it is OK for
// other objects to be inserted in the prototype chain.
JsValueRef wrapper = value;
bool hasExternalData = false;
do {
CHECK_JSRT(JsGetPrototype(wrapper, &wrapper));
if (wrapper == JS_INVALID_REFERENCE) {
return napi_invalid_arg;
}
CHECK_JSRT(JsHasExternalData(wrapper, &hasExternalData));
} while (!hasExternalData);
JsValueRef wrapper = JS_INVALID_REFERENCE;
CHECK_NAPI(jsrtimpl::FindWrapper(value, &wrapper));
RETURN_STATUS_IF_FALSE(wrapper != JS_INVALID_REFERENCE, napi_invalid_arg);

jsrtimpl::ExternalData* externalData;
CHECK_JSRT(JsGetExternalData(
Expand Down

0 comments on commit 9ab193b

Please sign in to comment.