@@ -35,6 +35,7 @@ using v8::Null;
35
35
using v8::Object;
36
36
using v8::ObjectTemplate;
37
37
using v8::Primitive;
38
+ using v8::PropertyCallbackInfo;
38
39
using v8::String;
39
40
using v8::Undefined;
40
41
using v8::Value;
@@ -594,6 +595,76 @@ void GetCompileCacheEntry(const FunctionCallbackInfo<Value>& args) {
594
595
isolate, v8::Null (isolate), names.data (), values.data (), names.size ()));
595
596
}
596
597
598
+ static void PathHelpersLazyGetter (Local<v8::Name> name,
599
+ const PropertyCallbackInfo<Value>& info) {
600
+ Isolate* isolate = info.GetIsolate ();
601
+ // This getter has no JavaScript function representation and is not
602
+ // invoked in the creation context.
603
+ // When this getter is invoked in a vm context, the `Realm::GetCurrent(info)`
604
+ // returns a nullptr and retrieve the creation context via `this` object and
605
+ // get the creation Realm.
606
+ Local<Value> receiver_val = info.This ();
607
+ if (!receiver_val->IsObject ()) {
608
+ THROW_ERR_INVALID_INVOCATION (isolate);
609
+ return ;
610
+ }
611
+ Local<Object> receiver = receiver_val.As <Object>();
612
+ Local<Context> context;
613
+ if (!receiver->GetCreationContext ().ToLocal (&context)) {
614
+ THROW_ERR_INVALID_INVOCATION (isolate);
615
+ return ;
616
+ }
617
+ Environment* env = Environment::GetCurrent (context);
618
+
619
+ node::Utf8Value url (isolate, info.Data ());
620
+ auto file_url = ada::parse (url.ToStringView ());
621
+ CHECK (file_url);
622
+ auto file_path = url::FileURLToPath (env, *file_url);
623
+ CHECK (file_path.has_value ());
624
+ std::string_view ret_view = file_path.value ();
625
+
626
+ node::Utf8Value utf8name (isolate, name);
627
+ auto plain_name = utf8name.ToStringView ();
628
+ if (plain_name == " dirname" ) {
629
+ #ifdef _WIN32
630
+ #define PATH_SEPARATOR ' \\ '
631
+ #else
632
+ #define PATH_SEPARATOR ' /'
633
+ #endif
634
+ auto index = ret_view.rfind (PATH_SEPARATOR);
635
+ CHECK (index != std::string_view::npos);
636
+ ret_view.remove_suffix (ret_view.size () - index );
637
+ #undef PATH_SEPARATOR
638
+ }
639
+ Local<Value> ret;
640
+ if (!ToV8Value (context, ret_view, isolate).ToLocal (&ret)) {
641
+ return ;
642
+ }
643
+ info.GetReturnValue ().Set (ret);
644
+ }
645
+ void InitImportMetaPathHelpers (const FunctionCallbackInfo<Value>& args) {
646
+ // target, url, shouldSetDirnameAndFilename, resolve
647
+ CHECK_GE (args.Length (), 2 );
648
+ CHECK (args[0 ]->IsObject ());
649
+ CHECK (args[1 ]->IsString ());
650
+
651
+ Isolate* isolate = args.GetIsolate ();
652
+ Local<Context> context = isolate->GetCurrentContext ();
653
+ Environment* env = Environment::GetCurrent (context);
654
+
655
+ auto target = args[0 ].As <Object>();
656
+
657
+ // N.B.: Order is important to keep keys in alphabetical order.
658
+ if (target
659
+ ->SetLazyDataProperty (
660
+ context, env->dirname_string (), PathHelpersLazyGetter, args[1 ])
661
+ .IsNothing () ||
662
+ target
663
+ ->SetLazyDataProperty (
664
+ context, env->filename_string (), PathHelpersLazyGetter, args[1 ])
665
+ .IsNothing ())
666
+ return ;
667
+ }
597
668
void SaveCompileCacheEntry (const FunctionCallbackInfo<Value>& args) {
598
669
Isolate* isolate = args.GetIsolate ();
599
670
Local<Context> context = isolate->GetCurrentContext ();
@@ -627,6 +698,7 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
627
698
SetMethod (isolate, target, " flushCompileCache" , FlushCompileCache);
628
699
SetMethod (isolate, target, " getCompileCacheEntry" , GetCompileCacheEntry);
629
700
SetMethod (isolate, target, " saveCompileCacheEntry" , SaveCompileCacheEntry);
701
+ SetMethod (isolate, target, " setLazyPathHelpers" , InitImportMetaPathHelpers);
630
702
}
631
703
632
704
void BindingData::CreatePerContextProperties (Local<Object> target,
@@ -682,6 +754,7 @@ void BindingData::RegisterExternalReferences(
682
754
registry->Register (FlushCompileCache);
683
755
registry->Register (GetCompileCacheEntry);
684
756
registry->Register (SaveCompileCacheEntry);
757
+ registry->Register (InitImportMetaPathHelpers);
685
758
}
686
759
687
760
} // namespace modules
0 commit comments