Skip to content

Commit

Permalink
src: refactor Environment::GetCurrent() usage
Browse files Browse the repository at this point in the history
Make `Environment::GetCurrent()` return `nullptr` if the current
`Context` is not a Node.js context, and for the relevant usage of
this function, either:

- Switch to the better `GetCurrent(args)` variant
- Turn functions in to no-ops where it makes sense
- Make it a `CHECK`, i.e. an API requirement, where it make sense
- Leave a `TODO` comment for verifying what, if anything, is to be done

PR-URL: #22819
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Eugene Ostroukhov <eostroukhov@google.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
  • Loading branch information
addaleax authored and targos committed Sep 18, 2018
1 parent 41fa976 commit 2e32a75
Show file tree
Hide file tree
Showing 15 changed files with 82 additions and 38 deletions.
9 changes: 7 additions & 2 deletions src/async_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -681,12 +681,16 @@ MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,


async_id AsyncHooksGetExecutionAsyncId(Isolate* isolate) {
return Environment::GetCurrent(isolate)->execution_async_id();
Environment* env = Environment::GetCurrent(isolate);
if (env == nullptr) return -1;
return env->execution_async_id();
}


async_id AsyncHooksGetTriggerAsyncId(Isolate* isolate) {
return Environment::GetCurrent(isolate)->trigger_async_id();
Environment* env = Environment::GetCurrent(isolate);
if (env == nullptr) return -1;
return env->trigger_async_id();
}


Expand All @@ -705,6 +709,7 @@ async_context EmitAsyncInit(Isolate* isolate,
v8::Local<v8::String> name,
async_id trigger_async_id) {
Environment* env = Environment::GetCurrent(isolate);
CHECK_NOT_NULL(env);

// Initialize async context struct
if (trigger_async_id == -1)
Expand Down
1 change: 1 addition & 0 deletions src/bootstrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ void PromiseRejectCallback(PromiseRejectMessage message) {
PromiseRejectEvent event = message.GetEvent();

Environment* env = Environment::GetCurrent(isolate);
if (env == nullptr) return;
Local<Function> callback;
Local<Value> value;

Expand Down
1 change: 1 addition & 0 deletions src/callback_scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ InternalCallbackScope::InternalCallbackScope(Environment* env,
object_(object),
callback_scope_(env) {
CHECK_IMPLIES(expect == kRequireResource, !object.IsEmpty());
CHECK_NOT_NULL(env);

if (!env->can_call_into_js()) {
failed_ = true;
Expand Down
9 changes: 9 additions & 0 deletions src/env-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,15 @@ inline Environment* Environment::GetCurrent(v8::Isolate* isolate) {
}

inline Environment* Environment::GetCurrent(v8::Local<v8::Context> context) {
if (UNLIKELY(context.IsEmpty() ||
context->GetNumberOfEmbedderDataFields() <
ContextEmbedderIndex::kContextTag ||
context->GetAlignedPointerFromEmbedderData(
ContextEmbedderIndex::kContextTag) !=
Environment::kNodeContextTagPtr)) {
return nullptr;
}

return static_cast<Environment*>(
context->GetAlignedPointerFromEmbedderData(
ContextEmbedderIndex::kEnvironment));
Expand Down
13 changes: 2 additions & 11 deletions src/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -449,18 +449,9 @@ void Environment::EnvPromiseHook(v8::PromiseHookType type,
v8::Local<v8::Value> parent) {
Local<v8::Context> context = promise->CreationContext();

// Grow the embedder data if necessary to make sure we are not out of bounds
// when reading the magic number.
context->SetAlignedPointerInEmbedderData(
ContextEmbedderIndex::kContextTagBoundary, nullptr);
int* magicNumberPtr = reinterpret_cast<int*>(
context->GetAlignedPointerFromEmbedderData(
ContextEmbedderIndex::kContextTag));
if (magicNumberPtr != Environment::kNodeContextTagPtr) {
return;
}

Environment* env = Environment::GetCurrent(context);
if (env == nullptr) return;

for (const PromiseHookCallback& hook : env->promise_hooks_) {
hook.cb_(type, promise, parent, hook.arg_);
}
Expand Down
5 changes: 2 additions & 3 deletions src/inspector_js_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,11 @@ void CallAndPauseOnStart(const FunctionCallbackInfo<v8::Value>& args) {
}

void InspectorConsoleCall(const FunctionCallbackInfo<Value>& info) {
Isolate* isolate = info.GetIsolate();
HandleScope handle_scope(isolate);
Environment* env = Environment::GetCurrent(info);
Isolate* isolate = env->isolate();
Local<Context> context = isolate->GetCurrentContext();
CHECK_LT(2, info.Length());
SlicedArguments call_args(info, /* start */ 3);
Environment* env = Environment::GetCurrent(isolate);
if (InspectorEnabled(env)) {
Local<Value> inspector_method = info[0];
CHECK(inspector_method->IsFunction());
Expand Down
6 changes: 4 additions & 2 deletions src/module_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ MaybeLocal<Module> ModuleWrap::ResolveCallback(Local<Context> context,
Local<String> specifier,
Local<Module> referrer) {
Environment* env = Environment::GetCurrent(context);
CHECK_NOT_NULL(env); // TODO(addaleax): Handle nullptr here.
Isolate* isolate = env->isolate();
if (env->module_map.count(referrer->GetIdentityHash()) == 0) {
env->ThrowError("linking error, unknown module");
Expand Down Expand Up @@ -700,6 +701,7 @@ static MaybeLocal<Promise> ImportModuleDynamically(
Local<String> specifier) {
Isolate* iso = context->GetIsolate();
Environment* env = Environment::GetCurrent(context);
CHECK_NOT_NULL(env); // TODO(addaleax): Handle nullptr here.
v8::EscapableHandleScope handle_scope(iso);

if (env->context() != context) {
Expand Down Expand Up @@ -750,8 +752,8 @@ void ModuleWrap::SetImportModuleDynamicallyCallback(

void ModuleWrap::HostInitializeImportMetaObjectCallback(
Local<Context> context, Local<Module> module, Local<Object> meta) {
Isolate* isolate = context->GetIsolate();
Environment* env = Environment::GetCurrent(context);
CHECK_NOT_NULL(env); // TODO(addaleax): Handle nullptr here.
ModuleWrap* module_wrap = GetFromModule(env, module);

if (module_wrap == nullptr) {
Expand All @@ -762,7 +764,7 @@ void ModuleWrap::HostInitializeImportMetaObjectCallback(
Local<Function> callback =
env->host_initialize_import_meta_object_callback();
Local<Value> args[] = { wrap, meta };
callback->Call(context, Undefined(isolate), arraysize(args), args)
callback->Call(context, Undefined(env->isolate()), arraysize(args), args)
.ToLocalChecked();
}

Expand Down
17 changes: 13 additions & 4 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,8 @@ namespace {
bool ShouldAbortOnUncaughtException(Isolate* isolate) {
HandleScope scope(isolate);
Environment* env = Environment::GetCurrent(isolate);
return env->should_abort_on_uncaught_toggle()[0] &&
return env != nullptr &&
env->should_abort_on_uncaught_toggle()[0] &&
!env->inside_should_not_abort_on_uncaught_scope();
}

Expand All @@ -639,13 +640,15 @@ bool ShouldAbortOnUncaughtException(Isolate* isolate) {

void AddPromiseHook(Isolate* isolate, promise_hook_func fn, void* arg) {
Environment* env = Environment::GetCurrent(isolate);
CHECK_NOT_NULL(env);
env->AddPromiseHook(fn, arg);
}

void AddEnvironmentCleanupHook(Isolate* isolate,
void (*fun)(void* arg),
void* arg) {
Environment* env = Environment::GetCurrent(isolate);
CHECK_NOT_NULL(env);
env->AddCleanupHook(fun, arg);
}

Expand All @@ -654,6 +657,7 @@ void RemoveEnvironmentCleanupHook(Isolate* isolate,
void (*fun)(void* arg),
void* arg) {
Environment* env = Environment::GetCurrent(isolate);
CHECK_NOT_NULL(env);
env->RemoveCleanupHook(fun, arg);
}

Expand Down Expand Up @@ -738,6 +742,7 @@ MaybeLocal<Value> MakeCallback(Isolate* isolate,
// Because of the AssignToContext() call in src/node_contextify.cc,
// the two contexts need not be the same.
Environment* env = Environment::GetCurrent(callback->CreationContext());
CHECK_NOT_NULL(env);
Context::Scope context_scope(env->context());
MaybeLocal<Value> ret = InternalMakeCallback(env, recv, callback,
argc, argv, asyncContext);
Expand Down Expand Up @@ -1376,6 +1381,7 @@ void FatalException(Isolate* isolate,
HandleScope scope(isolate);

Environment* env = Environment::GetCurrent(isolate);
CHECK_NOT_NULL(env); // TODO(addaleax): Handle nullptr here.
Local<Object> process_object = env->process_object();
Local<String> fatal_exception_string = env->fatal_exception_string();
Local<Value> fatal_exception_function =
Expand Down Expand Up @@ -1601,7 +1607,7 @@ static void GetInternalBinding(const FunctionCallbackInfo<Value>& args) {
}

static void GetLinkedBinding(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args.GetIsolate());
Environment* env = Environment::GetCurrent(args);

CHECK(args[0]->IsString());

Expand Down Expand Up @@ -2705,10 +2711,13 @@ void RunAtExit(Environment* env) {

uv_loop_t* GetCurrentEventLoop(Isolate* isolate) {
HandleScope handle_scope(isolate);
auto context = isolate->GetCurrentContext();
Local<Context> context = isolate->GetCurrentContext();
if (context.IsEmpty())
return nullptr;
return Environment::GetCurrent(context)->event_loop();
Environment* env = Environment::GetCurrent(context);
if (env == nullptr)
return nullptr;
return env->event_loop();
}


Expand Down
13 changes: 9 additions & 4 deletions src/node_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ class ThreadSafeFunction : public node::AsyncResource {
return napi_ok;
}

node::Environment::GetCurrent(env->isolate)->CloseHandle(
NodeEnv()->CloseHandle(
reinterpret_cast<uv_handle_t*>(&async),
[](uv_handle_t* handle) -> void {
ThreadSafeFunction* ts_fn =
Expand Down Expand Up @@ -1036,9 +1036,12 @@ class ThreadSafeFunction : public node::AsyncResource {
}

node::Environment* NodeEnv() {
// For some reason grabbing the Node.js environment requires a handle scope.
// Grabbing the Node.js environment requires a handle scope because it
// looks up fields on the current context.
v8::HandleScope scope(env->isolate);
return node::Environment::GetCurrent(env->isolate);
node::Environment* node_env = node::Environment::GetCurrent(env->isolate);
CHECK_NOT_NULL(node_env);
return node_env;
}

void MaybeStartIdle() {
Expand Down Expand Up @@ -1234,7 +1237,9 @@ void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
v8::Local<v8::Context> context,
napi_addon_register_func init) {
if (init == nullptr) {
node::Environment::GetCurrent(context)->ThrowError(
node::Environment* node_env = node::Environment::GetCurrent(context);
CHECK_NOT_NULL(node_env);
node_env->ThrowError(
"Module has no declared entry point.");
return;
}
Expand Down
7 changes: 6 additions & 1 deletion src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,9 @@ MaybeLocal<Object> New(Isolate* isolate,
MaybeLocal<Object> New(Isolate* isolate, size_t length) {
EscapableHandleScope handle_scope(isolate);
Local<Object> obj;
if (Buffer::New(Environment::GetCurrent(isolate), length).ToLocal(&obj))
Environment* env = Environment::GetCurrent(isolate);
CHECK_NOT_NULL(env); // TODO(addaleax): Handle nullptr here.
if (Buffer::New(env, length).ToLocal(&obj))
return handle_scope.Escape(obj);
return Local<Object>();
}
Expand Down Expand Up @@ -316,6 +318,7 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
MaybeLocal<Object> Copy(Isolate* isolate, const char* data, size_t length) {
EscapableHandleScope handle_scope(isolate);
Environment* env = Environment::GetCurrent(isolate);
CHECK_NOT_NULL(env); // TODO(addaleax): Handle nullptr here.
Local<Object> obj;
if (Buffer::Copy(env, data, length).ToLocal(&obj))
return handle_scope.Escape(obj);
Expand Down Expand Up @@ -365,6 +368,7 @@ MaybeLocal<Object> New(Isolate* isolate,
void* hint) {
EscapableHandleScope handle_scope(isolate);
Environment* env = Environment::GetCurrent(isolate);
CHECK_NOT_NULL(env); // TODO(addaleax): Handle nullptr here.
Local<Object> obj;
if (Buffer::New(env, data, length, callback, hint).ToLocal(&obj))
return handle_scope.Escape(obj);
Expand Down Expand Up @@ -403,6 +407,7 @@ MaybeLocal<Object> New(Environment* env,
MaybeLocal<Object> New(Isolate* isolate, char* data, size_t length) {
EscapableHandleScope handle_scope(isolate);
Environment* env = Environment::GetCurrent(isolate);
CHECK_NOT_NULL(env); // TODO(addaleax): Handle nullptr here.
Local<Object> obj;
if (Buffer::New(env, data, length).ToLocal(&obj))
return handle_scope.Escape(obj);
Expand Down
5 changes: 0 additions & 5 deletions src/node_context_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,11 @@ namespace node {
#define NODE_CONTEXT_TAG 35
#endif

#ifndef NODE_CONTEXT_TAG_BOUNDARY
#define NODE_CONTEXT_TAG_BOUNDARY 36
#endif

enum ContextEmbedderIndex {
kEnvironment = NODE_CONTEXT_EMBEDDER_DATA_INDEX,
kSandboxObject = NODE_CONTEXT_SANDBOX_OBJECT_INDEX,
kAllowWasmCodeGeneration = NODE_CONTEXT_ALLOW_WASM_CODE_GENERATION_INDEX,
kContextTag = NODE_CONTEXT_TAG,
kContextTagBoundary = NODE_CONTEXT_TAG_BOUNDARY,
};

} // namespace node
Expand Down
9 changes: 4 additions & 5 deletions src/node_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ void FSReqWrap::SetReturnValue(const FunctionCallbackInfo<Value>& args) {

void NewFSReqWrap(const FunctionCallbackInfo<Value>& args) {
CHECK(args.IsConstructCall());
Environment* env = Environment::GetCurrent(args.GetIsolate());
Environment* env = Environment::GetCurrent(args);
new FSReqWrap(env, args.This(), args[0]->IsTrue());
}

Expand Down Expand Up @@ -782,7 +782,7 @@ inline FSReqBase* GetReqWrap(Environment* env, Local<Value> value,
}

void Access(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args.GetIsolate());
Environment* env = Environment::GetCurrent(args);
HandleScope scope(env->isolate());

const int argc = args.Length();
Expand Down Expand Up @@ -2233,9 +2233,8 @@ void Initialize(Local<Object> target,

StatWatcher::Initialize(env, target);

// Create FunctionTemplate for FSReqWrap
Local<FunctionTemplate> fst =
FunctionTemplate::New(env->isolate(), NewFSReqWrap);
// Create FunctionTemplate for FSReqCallback
Local<FunctionTemplate> fst = env->NewFunctionTemplate(NewFSReqWrap);
fst->InstanceTemplate()->SetInternalFieldCount(1);
AsyncWrap::AddWrapMethods(env, fst);
Local<String> wrapString =
Expand Down
4 changes: 3 additions & 1 deletion src/node_internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,9 @@ class InternalCallbackScope {

class ThreadPoolWork {
public:
explicit inline ThreadPoolWork(Environment* env) : env_(env) {}
explicit inline ThreadPoolWork(Environment* env) : env_(env) {
CHECK_NOT_NULL(env);
}
inline virtual ~ThreadPoolWork() = default;

inline void ScheduleWork();
Expand Down
1 change: 1 addition & 0 deletions src/node_perf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ void TimerFunctionCall(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
HandleScope scope(isolate);
Environment* env = Environment::GetCurrent(isolate);
CHECK_NOT_NULL(env); // TODO(addaleax): Verify that this is correct.
Local<Context> context = env->context();
Local<Function> fn = args.Data().As<Function>();
size_t count = args.Length();
Expand Down
20 changes: 20 additions & 0 deletions test/cctest/test_environment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,26 @@ TEST_F(EnvironmentTest, MultipleEnvironmentsPerIsolate) {
EXPECT_TRUE(called_cb_2);
}

TEST_F(EnvironmentTest, NonNodeJSContext) {
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Env test_env {handle_scope, argv};

EXPECT_EQ(node::Environment::GetCurrent(v8::Local<v8::Context>()), nullptr);

node::Environment* env = *test_env;
EXPECT_EQ(node::Environment::GetCurrent(isolate_), env);
EXPECT_EQ(node::Environment::GetCurrent(env->context()), env);

v8::Local<v8::Context> context = v8::Context::New(isolate_);
EXPECT_EQ(node::Environment::GetCurrent(context), nullptr);
EXPECT_EQ(node::Environment::GetCurrent(isolate_), env);

v8::Context::Scope context_scope(context);
EXPECT_EQ(node::Environment::GetCurrent(context), nullptr);
EXPECT_EQ(node::Environment::GetCurrent(isolate_), nullptr);
}

static void at_exit_callback1(void* arg) {
called_cb_1 = true;
if (arg) {
Expand Down

0 comments on commit 2e32a75

Please sign in to comment.