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