|
17 | 17 | #include <vector>
|
18 | 18 | #include "uv.h"
|
19 | 19 | #include "node_api.h"
|
| 20 | +#include "node_internals.h" |
20 | 21 |
|
21 | 22 | #define NAPI_VERSION 1
|
22 | 23 |
|
@@ -156,14 +157,20 @@ class HandleScopeWrapper {
|
156 | 157 | // across different versions.
|
157 | 158 | class EscapableHandleScopeWrapper {
|
158 | 159 | public:
|
159 |
| - explicit EscapableHandleScopeWrapper(v8::Isolate* isolate) : scope(isolate) {} |
| 160 | + explicit EscapableHandleScopeWrapper(v8::Isolate* isolate) |
| 161 | + : scope(isolate), escape_called_(false) {} |
| 162 | + bool escape_called() const { |
| 163 | + return escape_called_; |
| 164 | + } |
160 | 165 | template <typename T>
|
161 | 166 | v8::Local<T> Escape(v8::Local<T> handle) {
|
| 167 | + escape_called_ = true; |
162 | 168 | return scope.Escape(handle);
|
163 | 169 | }
|
164 | 170 |
|
165 | 171 | private:
|
166 | 172 | v8::EscapableHandleScope scope;
|
| 173 | + bool escape_called_; |
167 | 174 | };
|
168 | 175 |
|
169 | 176 | napi_handle_scope JsHandleScopeFromV8HandleScope(HandleScopeWrapper* s) {
|
@@ -718,7 +725,8 @@ const char* error_messages[] = {nullptr,
|
718 | 725 | "An array was expected",
|
719 | 726 | "Unknown failure",
|
720 | 727 | "An exception is pending",
|
721 |
| - "The async work item was cancelled"}; |
| 728 | + "The async work item was cancelled", |
| 729 | + "napi_escape_handle already called on scope"}; |
722 | 730 |
|
723 | 731 | static napi_status napi_clear_last_error(napi_env env) {
|
724 | 732 | CHECK_ENV(env);
|
@@ -746,10 +754,14 @@ napi_status napi_get_last_error_info(napi_env env,
|
746 | 754 | CHECK_ENV(env);
|
747 | 755 | CHECK_ARG(env, result);
|
748 | 756 |
|
| 757 | + // you must update this assert to reference the last message |
| 758 | + // in the napi_status enum each time a new error message is added. |
| 759 | + // We don't have a napi_status_last as this would result in an ABI |
| 760 | + // change each time a message was added. |
749 | 761 | static_assert(
|
750 |
| - (sizeof (error_messages) / sizeof (*error_messages)) == napi_status_last, |
| 762 | + node::arraysize(error_messages) == napi_escape_called_twice + 1, |
751 | 763 | "Count of error messages must match count of error values");
|
752 |
| - assert(env->last_error.error_code < napi_status_last); |
| 764 | + assert(env->last_error.error_code <= napi_escape_called_twice); |
753 | 765 |
|
754 | 766 | // Wait until someone requests the last error information to fetch the error
|
755 | 767 | // message string
|
@@ -2211,9 +2223,12 @@ napi_status napi_escape_handle(napi_env env,
|
2211 | 2223 |
|
2212 | 2224 | v8impl::EscapableHandleScopeWrapper* s =
|
2213 | 2225 | v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope);
|
2214 |
| - *result = v8impl::JsValueFromV8LocalValue( |
2215 |
| - s->Escape(v8impl::V8LocalValueFromJsValue(escapee))); |
2216 |
| - return napi_clear_last_error(env); |
| 2226 | + if (!s->escape_called()) { |
| 2227 | + *result = v8impl::JsValueFromV8LocalValue( |
| 2228 | + s->Escape(v8impl::V8LocalValueFromJsValue(escapee))); |
| 2229 | + return napi_clear_last_error(env); |
| 2230 | + } |
| 2231 | + return napi_set_last_error(env, napi_escape_called_twice); |
2217 | 2232 | }
|
2218 | 2233 |
|
2219 | 2234 | napi_status napi_new_instance(napi_env env,
|
|
0 commit comments