@@ -348,6 +348,69 @@ static void IsInsideNodeModules(const FunctionCallbackInfo<Value>& args) {
348348 args.GetReturnValue ().Set (result);
349349}
350350
351+ static void DefineLazyPropertiesGetter (
352+ Local<v8::Name> name, const v8::PropertyCallbackInfo<Value>& info) {
353+ Realm* realm = Realm::GetCurrent (info);
354+ Isolate* isolate = realm->isolate ();
355+ auto context = isolate->GetCurrentContext ();
356+ Local<Value> arg = info.Data ();
357+ Local<Value> require_result;
358+ if (!realm->builtin_module_require ()
359+ ->Call (context, Null (isolate), 1 , &arg)
360+ .ToLocal (&require_result)) {
361+ // V8 will have scheduled an error to be thrown.
362+ return ;
363+ }
364+ Local<Value> ret;
365+ if (!require_result.As <v8::Object>()->Get (context, name).ToLocal (&ret)) {
366+ // V8 will have scheduled an error to be thrown.
367+ return ;
368+ }
369+ info.GetReturnValue ().Set (ret);
370+ }
371+ static void DefineLazyProperties (const FunctionCallbackInfo<Value>& args) {
372+ // target: object, id: string, keys: string[][, enumerable = true]
373+ CHECK_GE (args.Length (), 3 );
374+ // target: Object where to define the lazy properties.
375+ CHECK (args[0 ]->IsObject ());
376+ // id: Internal module to lazy-load where the API to expose are implemented.
377+ CHECK (args[1 ]->IsString ());
378+ // keys: Keys to map from `require(id)` and `target`.
379+ CHECK (args[2 ]->IsArray ());
380+ // enumerable: Whether the property should be enumerable.
381+ CHECK (args.Length () == 3 || args[3 ]->IsBoolean ());
382+
383+ Environment* env = Environment::GetCurrent (args);
384+ Isolate* isolate = env->isolate ();
385+ auto context = isolate->GetCurrentContext ();
386+
387+ auto target = args[0 ].As <Object>();
388+ Local<Value> id = args[1 ];
389+ v8::PropertyAttribute attribute =
390+ args.Length () == 3 || args[3 ]->IsTrue () ? v8::None : v8::DontEnum;
391+
392+ const Local<Array> keys = args[2 ].As <Array>();
393+ size_t length = keys->Length ();
394+ for (size_t i = 0 ; i < length; i++) {
395+ Local<Value> key;
396+ if (!keys->Get (context, i).ToLocal (&key)) {
397+ // V8 will have scheduled an error to be thrown.
398+ return ;
399+ }
400+ CHECK (key->IsString ());
401+ if (target
402+ ->SetLazyDataProperty (context,
403+ key.As <String>(),
404+ DefineLazyPropertiesGetter,
405+ id,
406+ attribute)
407+ .IsNothing ()) {
408+ // V8 will have scheduled an error to be thrown.
409+ return ;
410+ };
411+ }
412+ }
413+
351414void RegisterExternalReferences (ExternalReferenceRegistry* registry) {
352415 registry->Register (GetPromiseDetails);
353416 registry->Register (GetProxyDetails);
@@ -364,6 +427,8 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
364427 registry->Register (fast_guess_handle_type_.GetTypeInfo ());
365428 registry->Register (ParseEnv);
366429 registry->Register (IsInsideNodeModules);
430+ registry->Register (DefineLazyProperties);
431+ registry->Register (DefineLazyPropertiesGetter);
367432}
368433
369434void Initialize (Local<Object> target,
@@ -448,6 +513,7 @@ void Initialize(Local<Object> target,
448513 }
449514
450515 SetMethod (context, target, " isInsideNodeModules" , IsInsideNodeModules);
516+ SetMethod (context, target, " defineLazyProperties" , DefineLazyProperties);
451517 SetMethodNoSideEffect (
452518 context, target, " getPromiseDetails" , GetPromiseDetails);
453519 SetMethodNoSideEffect (context, target, " getProxyDetails" , GetProxyDetails);
0 commit comments