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 <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
1 parent b696049 commit 56f9fe7

File tree

6 files changed

+105
-81
lines changed

6 files changed

+105
-81
lines changed

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
const config = 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-
const DOMException = lazyDOMExceptionClass();
35-
exposeInterface(globalThis, 'DOMException', DOMException);
36-
return DOMException;
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-
function defineLazyProperties(target, id, keys, enumerable = true) {
605-
const descriptors = { __proto__: null };
606-
let mod;
607-
for (let i = 0; i < keys.length; i++) {
608-
const key = keys[i];
609-
let lazyLoadedValue;
610-
function set(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-
function get() {
622-
mod ??= require(id);
623-
if (lazyLoadedValue === undefined) {
624-
lazyLoadedValue = mod[key];
625-
set(lazyLoadedValue);
626-
}
627-
return lazyLoadedValue;
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
function defineReplaceableLazyAttribute(target, id, keys, writable = true, check) {
645606
let mod;
646607
for (let i = 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+
static void ExposeLazyDOMExceptionPropertyGetter(
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+
static void ExposeLazyDOMExceptionProperty(
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
static void CreatePerIsolateProperties(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+
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+
351414
void 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

369434
void 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);

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-
const lazyProperties = [
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-
const script = 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
async runJsTests() {

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
const runner = new WPTRunner('webidl/ecmascript-binding/es-exceptions');
66

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

0 commit comments

Comments
 (0)