@@ -30,6 +30,7 @@ using v8::NewStringType;
30
30
using v8::Object;
31
31
using v8::ObjectTemplate;
32
32
using v8::Primitive;
33
+ using v8::PropertyCallbackInfo;
33
34
using v8::String;
34
35
using v8::Undefined;
35
36
using v8::Value;
@@ -529,6 +530,77 @@ void GetCompileCacheDir(const FunctionCallbackInfo<Value>& args) {
529
530
.ToLocalChecked ());
530
531
}
531
532
533
+ static void PathHelpersLazyGetter (Local<v8::Name> name,
534
+ const PropertyCallbackInfo<Value>& info) {
535
+ Isolate* isolate = info.GetIsolate ();
536
+ // This getter has no JavaScript function representation and is not
537
+ // invoked in the creation context.
538
+ // When this getter is invoked in a vm context, the `Realm::GetCurrent(info)`
539
+ // returns a nullptr and retrieve the creation context via `this` object and
540
+ // get the creation Realm.
541
+ Local<Value> receiver_val = info.This ();
542
+ if (!receiver_val->IsObject ()) {
543
+ THROW_ERR_INVALID_INVOCATION (isolate);
544
+ return ;
545
+ }
546
+ Local<Object> receiver = receiver_val.As <Object>();
547
+ Local<Context> context;
548
+ if (!receiver->GetCreationContext ().ToLocal (&context)) {
549
+ THROW_ERR_INVALID_INVOCATION (isolate);
550
+ return ;
551
+ }
552
+ Environment* env = Environment::GetCurrent (context);
553
+
554
+ node::Utf8Value url (isolate, info.Data ());
555
+ auto file_url = ada::parse (url.ToStringView ());
556
+ CHECK (file_url);
557
+ auto file_path = url::FileURLToPath (env, *file_url);
558
+ CHECK (file_path.has_value ());
559
+ std::string_view ret_view = file_path.value ();
560
+
561
+ node::Utf8Value utf8name (isolate, name);
562
+ auto plain_name = utf8name.ToStringView ();
563
+ if (plain_name == " dirname" ) {
564
+ #ifdef _WIN32
565
+ #define PATH_SEPARATOR ' \\ '
566
+ #else
567
+ #define PATH_SEPARATOR ' /'
568
+ #endif
569
+ auto index = ret_view.rfind (PATH_SEPARATOR);
570
+ CHECK (index != std::string_view::npos);
571
+ ret_view.remove_suffix (ret_view.size () - index );
572
+ #undef PATH_SEPARATOR
573
+ }
574
+ Local<Value> ret;
575
+ if (!ToV8Value (context, ret_view, isolate).ToLocal (&ret)) {
576
+ return ;
577
+ }
578
+ info.GetReturnValue ().Set (ret);
579
+ }
580
+ void InitImportMetaPathHelpers (const FunctionCallbackInfo<Value>& args) {
581
+ // target, url, shouldSetDirnameAndFilename, resolve
582
+ CHECK_GE (args.Length (), 2 );
583
+ CHECK (args[0 ]->IsObject ());
584
+ CHECK (args[1 ]->IsString ());
585
+
586
+ Isolate* isolate = args.GetIsolate ();
587
+ Local<Context> context = isolate->GetCurrentContext ();
588
+ Environment* env = Environment::GetCurrent (context);
589
+
590
+ auto target = args[0 ].As <Object>();
591
+
592
+ // N.B.: Order is important to keep keys in alphabetical order.
593
+ if (target
594
+ ->SetLazyDataProperty (
595
+ context, env->dirname_string (), PathHelpersLazyGetter, args[1 ])
596
+ .IsNothing () ||
597
+ target
598
+ ->SetLazyDataProperty (
599
+ context, env->filename_string (), PathHelpersLazyGetter, args[1 ])
600
+ .IsNothing ())
601
+ return ;
602
+ }
603
+
532
604
void BindingData::CreatePerIsolateProperties (IsolateData* isolate_data,
533
605
Local<ObjectTemplate> target) {
534
606
Isolate* isolate = isolate_data->isolate ();
@@ -547,6 +619,7 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
547
619
SetMethod (isolate, target, " enableCompileCache" , EnableCompileCache);
548
620
SetMethod (isolate, target, " getCompileCacheDir" , GetCompileCacheDir);
549
621
SetMethod (isolate, target, " flushCompileCache" , FlushCompileCache);
622
+ SetMethod (isolate, target, " setLazyPathHelpers" , InitImportMetaPathHelpers);
550
623
}
551
624
552
625
void BindingData::CreatePerContextProperties (Local<Object> target,
@@ -581,6 +654,7 @@ void BindingData::RegisterExternalReferences(
581
654
registry->Register (EnableCompileCache);
582
655
registry->Register (GetCompileCacheDir);
583
656
registry->Register (FlushCompileCache);
657
+ registry->Register (InitImportMetaPathHelpers);
584
658
}
585
659
586
660
} // namespace modules
0 commit comments