diff --git a/src/node_perf.cc b/src/node_perf.cc
index 1e1fe13d938566..da2405d3752012 100644
--- a/src/node_perf.cc
+++ b/src/node_perf.cc
@@ -310,7 +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.
+  CHECK_NOT_NULL(env);
   Local<Context> context = env->context();
   Local<Function> fn = args.Data().As<Function>();
   size_t count = args.Length();
diff --git a/test/addons/non-node-context/binding.cc b/test/addons/non-node-context/binding.cc
new file mode 100644
index 00000000000000..324f5c5a1ef16f
--- /dev/null
+++ b/test/addons/non-node-context/binding.cc
@@ -0,0 +1,55 @@
+#include <node.h>
+#include <assert.h>
+
+namespace {
+
+using v8::Context;
+using v8::Function;
+using v8::FunctionTemplate;
+using v8::Isolate;
+using v8::Local;
+using v8::MaybeLocal;
+using v8::NewStringType;
+using v8::Object;
+using v8::Script;
+using v8::String;
+using v8::Value;
+
+inline void RunInNewContext(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  Isolate* isolate = args.GetIsolate();
+  Local<Context> context = Context::New(isolate);
+  Context::Scope context_scope(context);
+
+  context->Global()->Set(
+      context,
+      String::NewFromUtf8(isolate, "data", NewStringType::kNormal)
+          .ToLocalChecked(),
+      args[1]).FromJust();
+
+  assert(args[0]->IsString());  // source code
+  Local<Script> script;
+  Local<Value> ret;
+  if (!Script::Compile(context, args[0].As<String>()).ToLocal(&script) ||
+      !script->Run(context).ToLocal(&ret)) {
+    return;
+  }
+
+  args.GetReturnValue().Set(ret);
+}
+
+inline void Initialize(Local<Object> exports,
+                       Local<Value> module,
+                       Local<Context> context) {
+  Isolate* isolate = context->GetIsolate();
+  Local<String> key = String::NewFromUtf8(
+      isolate, "runInNewContext", NewStringType::kNormal).ToLocalChecked();
+  Local<Function> value = FunctionTemplate::New(isolate, RunInNewContext)
+                   ->GetFunction(context)
+                   .ToLocalChecked();
+  assert(exports->Set(context, key, value).IsJust());
+}
+
+}  // anonymous namespace
+
+NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME, Initialize)
diff --git a/test/addons/non-node-context/binding.gyp b/test/addons/non-node-context/binding.gyp
new file mode 100644
index 00000000000000..b83bae308260f2
--- /dev/null
+++ b/test/addons/non-node-context/binding.gyp
@@ -0,0 +1,8 @@
+{
+  'targets': [
+    {
+      'target_name': 'binding',
+      'sources': ['binding.cc']
+    },
+  ]
+}
diff --git a/test/addons/non-node-context/test-perf-hooks-timerify.js b/test/addons/non-node-context/test-perf-hooks-timerify.js
new file mode 100644
index 00000000000000..10a9ab8064227e
--- /dev/null
+++ b/test/addons/non-node-context/test-perf-hooks-timerify.js
@@ -0,0 +1,17 @@
+'use strict';
+
+const common = require('../../common');
+const assert = require('assert');
+const { runInNewContext } = require(`./build/${common.buildType}/binding`);
+const { performance } = require('perf_hooks');
+
+// Check that performance.timerify() works when called from another context,
+// for a function created in another context.
+
+const check = runInNewContext(`
+const { performance, assert } = data;
+const timerified = performance.timerify(function() { return []; });
+assert.strictEqual(timerified().constructor, Array);
+'success';
+`, { performance, assert });
+assert.strictEqual(check, 'success');