src: implement IsInsideNodeModules() in C++ · nodejs/node@ececd22
@@ -254,6 +254,54 @@ static void ParseEnv(const FunctionCallbackInfo<Value>& args) {
254254 args.GetReturnValue().Set(dotenv.ToObject(env));
255255}
256256257+bool starts_with(std::string_view view, std::string_view prefix) {
258+return view.size() >= prefix.size() &&
259+ view.substr(0, prefix.size()) == prefix;
260+}
261+262+static void IsInsideNodeModules(const FunctionCallbackInfo<Value>& args) {
263+ Isolate* isolate = args.GetIsolate();
264+CHECK_EQ(args.Length(), 2);
265+CHECK(args[0]->IsInt32()); // frame_limit
266+// The second argument is the default value.
267+268+int frames_limit = args[0].As<v8::Int32>()->Value();
269+ Local<StackTrace> stack =
270+StackTrace::CurrentStackTrace(isolate, frames_limit);
271+int frame_count = stack->GetFrameCount();
272+273+// If the search requires looking into more than |frames_limit| frames, give
274+// up and return the specified default value.
275+if (frame_count == frames_limit) {
276+return args.GetReturnValue().Set(args[1]);
277+ }
278+279+bool result = false;
280+for (int i = 0; i < frame_count; ++i) {
281+ Local<StackFrame> stack_frame = stack->GetFrame(isolate, i);
282+ Local<String> script_name = stack_frame->GetScriptName();
283+284+if (script_name.IsEmpty() || script_name->Length() == 0) {
285+continue;
286+ }
287+ Utf8Value script_name_utf8(isolate, script_name);
288+ std::string_view script_name_str = script_name_utf8.ToStringView();
289+if (starts_with(script_name_str,
290+"node:")) { // Ported to work with C++17 on 20.x.
291+continue;
292+ }
293+if (script_name_str.find("/node_modules/") != std::string::npos ||
294+ script_name_str.find("\\node_modules\\") != std::string::npos ||
295+ script_name_str.find("/node_modules\\") != std::string::npos ||
296+ script_name_str.find("\\node_modules/") != std::string::npos) {
297+ result = true;
298+break;
299+ }
300+ }
301+302+ args.GetReturnValue().Set(result);
303+}
304+257305void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
258306 registry->Register(GetPromiseDetails);
259307 registry->Register(GetProxyDetails);
@@ -269,6 +317,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
269317 registry->Register(FastGuessHandleType);
270318 registry->Register(fast_guess_handle_type_.GetTypeInfo());
271319 registry->Register(ParseEnv);
320+ registry->Register(IsInsideNodeModules);
272321}
273322274323void Initialize(Local<Object> target,
@@ -338,6 +387,7 @@ void Initialize(Local<Object> target,
338387 target->Set(context, env->constants_string(), constants).Check();
339388 }
340389390+SetMethod(context, target, "isInsideNodeModules", IsInsideNodeModules);
341391SetMethodNoSideEffect(
342392 context, target, "getPromiseDetails", GetPromiseDetails);
343393SetMethodNoSideEffect(context, target, "getProxyDetails", GetProxyDetails);