Skip to content

Commit 56f9fe7

Browse files
aduh95targos
authored andcommitted
src: port defineLazyProperties to native code
This allows us to have getters not observable from JS side. PR-URL: #57081 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
1 parent b696049 commit 56f9fe7

6 files changed

Lines changed: 105 additions & 81 deletions

File tree

‎lib/internal/bootstrap/web/exposed-wildcard.js‎

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ const {
1212

1313
const{
1414
exposeInterface,
15-
lazyDOMExceptionClass,
1615
exposeLazyInterfaces,
17-
exposeGetterAndSetter,
1816
exposeNamespace,
1917
}=require('internal/util');
2018
constconfig=internalBinding('config');
19+
const{ exposeLazyDOMExceptionProperty }=internalBinding('messaging');
2120

2221
// https://console.spec.whatwg.org/#console-namespace
2322
exposeNamespace(globalThis,'console',
@@ -28,16 +27,7 @@ const { URL, URLSearchParams } = require('internal/url');
2827
exposeInterface(globalThis,'URL',URL);
2928
// https://url.spec.whatwg.org/#urlsearchparams
3029
exposeInterface(globalThis,'URLSearchParams',URLSearchParams);
31-
exposeGetterAndSetter(globalThis,
32-
'DOMException',
33-
()=>{
34-
constDOMException=lazyDOMExceptionClass();
35-
exposeInterface(globalThis,'DOMException',DOMException);
36-
returnDOMException;
37-
},
38-
(value)=>{
39-
exposeInterface(globalThis,'DOMException',value);
40-
});
30+
exposeLazyDOMExceptionProperty(globalThis);
4131

4232
// https://dom.spec.whatwg.org/#interface-abortcontroller
4333
// Lazy ones.

‎lib/internal/util.js‎

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const {
5555
const{ signals }=internalBinding('constants').os;
5656
const{
5757
guessHandleType: _guessHandleType,
58+
defineLazyProperties,
5859
privateSymbols: {
5960
arrow_message_private_symbol,
6061
decorated_private_symbol,
@@ -601,46 +602,6 @@ function exposeGetterAndSetter(target, name, getter, setter = undefined) {
601602
});
602603
}
603604

604-
functiondefineLazyProperties(target,id,keys,enumerable=true){
605-
constdescriptors={__proto__: null};
606-
letmod;
607-
for(leti=0;i<keys.length;i++){
608-
constkey=keys[i];
609-
letlazyLoadedValue;
610-
functionset(value){
611-
ObjectDefineProperty(target,key,{
612-
__proto__: null,
613-
writable: true,
614-
value,
615-
});
616-
}
617-
ObjectDefineProperty(set,'name',{
618-
__proto__: null,
619-
value: `set ${key}`,
620-
});
621-
functionget(){
622-
mod??=require(id);
623-
if(lazyLoadedValue===undefined){
624-
lazyLoadedValue=mod[key];
625-
set(lazyLoadedValue);
626-
}
627-
returnlazyLoadedValue;
628-
}
629-
ObjectDefineProperty(get,'name',{
630-
__proto__: null,
631-
value: `get ${key}`,
632-
});
633-
descriptors[key]={
634-
__proto__: null,
635-
configurable: true,
636-
enumerable,
637-
get,
638-
set,
639-
};
640-
}
641-
ObjectDefineProperties(target,descriptors);
642-
}
643-
644605
functiondefineReplaceableLazyAttribute(target,id,keys,writable=true,check){
645606
letmod;
646607
for(leti=0;i<keys.length;i++){

‎src/node_messaging.cc‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,6 +1645,36 @@ static void BroadcastChannel(const FunctionCallbackInfo<Value>& args) {
16451645
}
16461646
}
16471647

1648+
staticvoidExposeLazyDOMExceptionPropertyGetter(
1649+
Local<v8::Name> name, const v8::PropertyCallbackInfo<Value>& info) {
1650+
auto context = info.GetIsolate()->GetCurrentContext();
1651+
Local<Function> domexception;
1652+
if (!GetDOMException(context).ToLocal(&domexception)) {
1653+
// V8 will have scheduled an error to be thrown.
1654+
return;
1655+
}
1656+
info.GetReturnValue().Set(domexception);
1657+
}
1658+
staticvoidExposeLazyDOMExceptionProperty(
1659+
const FunctionCallbackInfo<Value>& args) {
1660+
CHECK_GE(args.Length(), 1);
1661+
CHECK(args[0]->IsObject());
1662+
1663+
Isolate* isolate = args.GetIsolate();
1664+
auto target = args[0].As<Object>();
1665+
1666+
if (target
1667+
->SetLazyDataProperty(isolate->GetCurrentContext(),
1668+
FIXED_ONE_BYTE_STRING(isolate, "DOMException"),
1669+
ExposeLazyDOMExceptionPropertyGetter,
1670+
Local<Value>(),
1671+
v8::DontEnum)
1672+
.IsNothing()) {
1673+
// V8 will have scheduled an error to be thrown.
1674+
return;
1675+
}
1676+
}
1677+
16481678
staticvoidCreatePerIsolateProperties(IsolateData* isolate_data,
16491679
Local<ObjectTemplate> target) {
16501680
Isolate* isolate = isolate_data->isolate();
@@ -1669,6 +1699,10 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,
16691699
isolate_data->message_port_constructor_string(),
16701700
GetMessagePortConstructorTemplate(isolate_data));
16711701

1702+
SetMethod(isolate,
1703+
target,
1704+
"exposeLazyDOMExceptionProperty",
1705+
ExposeLazyDOMExceptionProperty);
16721706
// These are not methods on the MessagePort prototype, because
16731707
// the browser equivalents do not provide them.
16741708
SetMethod(isolate, target, "stopMessagePort", MessagePort::Stop);
@@ -1714,6 +1748,8 @@ static void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
17141748
registry->Register(MessagePort::MoveToContext);
17151749
registry->Register(SetDeserializerCreateObjectFunction);
17161750
registry->Register(StructuredClone);
1751+
registry->Register(ExposeLazyDOMExceptionProperty);
1752+
registry->Register(ExposeLazyDOMExceptionPropertyGetter);
17171753
}
17181754

17191755
} // anonymous namespace

‎src/node_util.cc‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,69 @@ static void IsInsideNodeModules(const FunctionCallbackInfo<Value>& args) {
348348
args.GetReturnValue().Set(result);
349349
}
350350

351+
staticvoidDefineLazyPropertiesGetter(
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+
staticvoidDefineLazyProperties(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+
351414
voidRegisterExternalReferences(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

369434
voidInitialize(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);

‎test/common/wpt.js‎

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,6 @@ class WPTRunner {
595595
switch(name){
596596
case'Window': {
597597
this.globalThisInitScripts.push('globalThis.Window = Object.getPrototypeOf(globalThis).constructor;');
598-
this.loadLazyGlobals();
599598
break;
600599
}
601600

@@ -609,32 +608,6 @@ class WPTRunner {
609608
}
610609
}
611610

612-
loadLazyGlobals(){
613-
constlazyProperties=[
614-
'DOMException',
615-
'Performance','PerformanceEntry','PerformanceMark','PerformanceMeasure',
616-
'PerformanceObserver','PerformanceObserverEntryList','PerformanceResourceTiming',
617-
'Blob','atob','btoa',
618-
'MessageChannel','MessagePort','MessageEvent',
619-
'EventTarget','Event',
620-
'AbortController','AbortSignal',
621-
'performance',
622-
'TransformStream','TransformStreamDefaultController',
623-
'WritableStream','WritableStreamDefaultController','WritableStreamDefaultWriter',
624-
'ReadableStream','ReadableStreamDefaultReader',
625-
'ReadableStreamBYOBReader','ReadableStreamBYOBRequest',
626-
'ReadableByteStreamController','ReadableStreamDefaultController',
627-
'ByteLengthQueuingStrategy','CountQueuingStrategy',
628-
'TextEncoder','TextDecoder','TextEncoderStream','TextDecoderStream',
629-
'CompressionStream','DecompressionStream',
630-
];
631-
if(Boolean(process.versions.openssl)&&!process.env.NODE_SKIP_CRYPTO){
632-
lazyProperties.push('crypto','Crypto','CryptoKey','SubtleCrypto');
633-
}
634-
constscript=lazyProperties.map((name)=>`globalThis.${name};`).join('\n');
635-
this.globalThisInitScripts.push(script);
636-
}
637-
638611
// TODO(joyeecheung): work with the upstream to port more tests in .html
639612
// to .js.
640613
asyncrunJsTests(){

‎test/wpt/test-domexception.js‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,4 @@ const { WPTRunner } = require('../common/wpt');
44

55
construnner=newWPTRunner('webidl/ecmascript-binding/es-exceptions');
66

7-
runner.loadLazyGlobals();
8-
97
runner.runJsTests();

0 commit comments

Comments
 (0)