|
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