Skip to content

Commit f4fb8da

Browse files
committed
lib: distinguish webidl interfaces with the extended property "Exposed"
PR-URL: nodejs#46809 Refs: nodejs#42528 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
1 parent c95ceef commit f4fb8da

File tree

6 files changed

+140
-87
lines changed

6 files changed

+140
-87
lines changed

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

+10-46
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
'use strict';
22

3+
/**
4+
* This file exposes web interfaces that is defined with the WebIDL
5+
* [Exposed=*] extended attribute.
6+
* See more details at https://webidl.spec.whatwg.org/#Exposed.
7+
*/
8+
39
const {
4-
ObjectDefineProperty,
510
globalThis,
611
} = primordials;
712

813
const {
9-
defineOperation,
1014
exposeInterface,
1115
lazyDOMExceptionClass,
12-
defineLazyProperties,
13-
defineReplaceableLazyAttribute,
1416
exposeLazyInterfaces,
17+
exposeGetterAndSetter,
18+
exposeNamespace,
1519
} = require('internal/util');
1620
const config = internalBinding('config');
1721

@@ -35,36 +39,17 @@ exposeGetterAndSetter(globalThis,
3539
exposeInterface(globalThis, 'DOMException', value);
3640
});
3741

38-
// https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope
39-
const timers = require('timers');
40-
defineOperation(globalThis, 'clearInterval', timers.clearInterval);
41-
defineOperation(globalThis, 'clearTimeout', timers.clearTimeout);
42-
defineOperation(globalThis, 'setInterval', timers.setInterval);
43-
defineOperation(globalThis, 'setTimeout', timers.setTimeout);
44-
42+
// https://dom.spec.whatwg.org/#interface-abortcontroller
4543
// Lazy ones.
46-
exposeLazyInterfaces(globalThis, 'internal/worker/io', ['BroadcastChannel']);
4744
exposeLazyInterfaces(globalThis, 'internal/abort_controller', [
4845
'AbortController', 'AbortSignal',
4946
]);
47+
// https://dom.spec.whatwg.org/#interface-eventtarget
5048
const {
5149
EventTarget, Event,
5250
} = require('internal/event_target');
5351
exposeInterface(globalThis, 'Event', Event);
5452
exposeInterface(globalThis, 'EventTarget', EventTarget);
55-
exposeLazyInterfaces(globalThis, 'internal/worker/io', [
56-
'MessageChannel', 'MessagePort', 'MessageEvent',
57-
]);
58-
defineLazyProperties(globalThis, 'buffer', ['atob', 'btoa']);
59-
// https://www.w3.org/TR/FileAPI/#dfn-Blob
60-
exposeLazyInterfaces(globalThis, 'internal/blob', ['Blob']);
61-
// https://www.w3.org/TR/hr-time-2/#the-performance-attribute
62-
exposeLazyInterfaces(globalThis, 'perf_hooks', [
63-
'Performance', 'PerformanceEntry', 'PerformanceMark', 'PerformanceMeasure',
64-
'PerformanceObserver', 'PerformanceObserverEntryList', 'PerformanceResourceTiming',
65-
]);
66-
67-
defineReplaceableLazyAttribute(globalThis, 'perf_hooks', ['performance']);
6853

6954
// https://encoding.spec.whatwg.org/#textencoder
7055
// https://encoding.spec.whatwg.org/#textdecoder
@@ -87,27 +72,6 @@ function createGlobalConsole() {
8772
return consoleFromNode;
8873
}
8974

90-
// https://heycam.github.io/webidl/#es-namespaces
91-
function exposeNamespace(target, name, namespaceObject) {
92-
ObjectDefineProperty(target, name, {
93-
__proto__: null,
94-
writable: true,
95-
enumerable: false,
96-
configurable: true,
97-
value: namespaceObject,
98-
});
99-
}
100-
101-
function exposeGetterAndSetter(target, name, getter, setter = undefined) {
102-
ObjectDefineProperty(target, name, {
103-
__proto__: null,
104-
enumerable: false,
105-
configurable: true,
106-
get: getter,
107-
set: setter,
108-
});
109-
}
110-
11175
// Web Streams API
11276
exposeLazyInterfaces(
11377
globalThis,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use strict';
2+
3+
/**
4+
* This file exposes web interfaces that is defined with the WebIDL
5+
* Exposed=(Window,Worker) extended attribute or exposed in
6+
* WindowOrWorkerGlobalScope mixin.
7+
* See more details at https://webidl.spec.whatwg.org/#Exposed and
8+
* https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope.
9+
*/
10+
11+
const {
12+
globalThis,
13+
} = primordials;
14+
15+
const {
16+
defineOperation,
17+
defineLazyProperties,
18+
defineReplaceableLazyAttribute,
19+
exposeLazyInterfaces,
20+
} = require('internal/util');
21+
22+
// https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope
23+
const timers = require('timers');
24+
defineOperation(globalThis, 'clearInterval', timers.clearInterval);
25+
defineOperation(globalThis, 'clearTimeout', timers.clearTimeout);
26+
defineOperation(globalThis, 'setInterval', timers.setInterval);
27+
defineOperation(globalThis, 'setTimeout', timers.setTimeout);
28+
29+
// https://html.spec.whatwg.org/multipage/web-messaging.html#broadcasting-to-other-browsing-contexts
30+
exposeLazyInterfaces(globalThis, 'internal/worker/io', ['BroadcastChannel']);
31+
exposeLazyInterfaces(globalThis, 'internal/worker/io', [
32+
'MessageChannel', 'MessagePort', 'MessageEvent',
33+
]);
34+
defineLazyProperties(globalThis, 'buffer', ['atob', 'btoa']);
35+
// https://www.w3.org/TR/FileAPI/#dfn-Blob
36+
exposeLazyInterfaces(globalThis, 'internal/blob', ['Blob']);
37+
// https://www.w3.org/TR/hr-time-2/#the-performance-attribute
38+
exposeLazyInterfaces(globalThis, 'perf_hooks', [
39+
'Performance', 'PerformanceEntry', 'PerformanceMark', 'PerformanceMeasure',
40+
'PerformanceObserver', 'PerformanceObserverEntryList', 'PerformanceResourceTiming',
41+
]);
42+
43+
defineReplaceableLazyAttribute(globalThis, 'perf_hooks', ['performance']);
44+
45+
// https://w3c.github.io/FileAPI/#creating-revoking
46+
const { installObjectURLMethods } = require('internal/url');
47+
installObjectURLMethods();

lib/internal/process/pre_execution.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ function setupFetch() {
262262
});
263263
}
264264

265-
// TODO(aduh95): move this to internal/bootstrap/browser when the CLI flag is
265+
// TODO(aduh95): move this to internal/bootstrap/web/* when the CLI flag is
266266
// removed.
267267
function setupWebCrypto() {
268268
if (process.config.variables.node_no_browser_globals ||
@@ -310,7 +310,7 @@ function setupCodeCoverage() {
310310
}
311311
}
312312

313-
// TODO(daeyeon): move this to internal/bootstrap/browser when the CLI flag is
313+
// TODO(daeyeon): move this to internal/bootstrap/web/* when the CLI flag is
314314
// removed.
315315
function setupCustomEvent() {
316316
if (process.config.variables.node_no_browser_globals ||

lib/internal/url.js

+54-36
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,6 @@ const {
9393
updateUrl,
9494
} = internalBinding('url');
9595

96-
const {
97-
storeDataObject,
98-
revokeDataObject,
99-
} = internalBinding('blob');
100-
10196
const FORWARD_SLASH = /\//g;
10297

10398
const context = Symbol('context');
@@ -782,35 +777,6 @@ class URL {
782777
return this[context].href;
783778
}
784779

785-
static createObjectURL(obj) {
786-
const cryptoRandom = lazyCryptoRandom();
787-
if (cryptoRandom === undefined)
788-
throw new ERR_NO_CRYPTO();
789-
790-
const blob = lazyBlob();
791-
if (!blob.isBlob(obj))
792-
throw new ERR_INVALID_ARG_TYPE('obj', 'Blob', obj);
793-
794-
const id = cryptoRandom.randomUUID();
795-
796-
storeDataObject(id, obj[blob.kHandle], obj.size, obj.type);
797-
798-
return `blob:nodedata:${id}`;
799-
}
800-
801-
static revokeObjectURL(url) {
802-
url = `${url}`;
803-
try {
804-
// TODO(@anonrig): Remove this try/catch by calling `parse` directly.
805-
const parsed = new URL(url);
806-
const split = StringPrototypeSplit(parsed.pathname, ':');
807-
if (split.length === 2)
808-
revokeDataObject(split[1]);
809-
} catch {
810-
// If there's an error, it's ignored.
811-
}
812-
}
813-
814780
static canParse(url, base = undefined) {
815781
url = `${url}`;
816782

@@ -841,8 +807,6 @@ ObjectDefineProperties(URL.prototype, {
841807
});
842808

843809
ObjectDefineProperties(URL, {
844-
createObjectURL: kEnumerableProperty,
845-
revokeObjectURL: kEnumerableProperty,
846810
canParse: {
847811
__proto__: null,
848812
configurable: true,
@@ -851,6 +815,59 @@ ObjectDefineProperties(URL, {
851815
},
852816
});
853817

818+
function installObjectURLMethods() {
819+
const {
820+
storeDataObject,
821+
revokeDataObject,
822+
} = internalBinding('blob');
823+
824+
function createObjectURL(obj) {
825+
const cryptoRandom = lazyCryptoRandom();
826+
if (cryptoRandom === undefined)
827+
throw new ERR_NO_CRYPTO();
828+
829+
const blob = lazyBlob();
830+
if (!blob.isBlob(obj))
831+
throw new ERR_INVALID_ARG_TYPE('obj', 'Blob', obj);
832+
833+
const id = cryptoRandom.randomUUID();
834+
835+
storeDataObject(id, obj[blob.kHandle], obj.size, obj.type);
836+
837+
return `blob:nodedata:${id}`;
838+
}
839+
840+
function revokeObjectURL(url) {
841+
url = `${url}`;
842+
try {
843+
// TODO(@anonrig): Remove this try/catch by calling `parse` directly.
844+
const parsed = new URL(url);
845+
const split = StringPrototypeSplit(parsed.pathname, ':');
846+
if (split.length === 2)
847+
revokeDataObject(split[1]);
848+
} catch {
849+
// If there's an error, it's ignored.
850+
}
851+
}
852+
853+
ObjectDefineProperties(URL, {
854+
createObjectURL: {
855+
__proto__: null,
856+
configurable: true,
857+
writable: true,
858+
enumerable: true,
859+
value: createObjectURL,
860+
},
861+
revokeObjectURL: {
862+
__proto__: null,
863+
configurable: true,
864+
writable: true,
865+
enumerable: true,
866+
value: revokeObjectURL,
867+
},
868+
});
869+
}
870+
854871
// application/x-www-form-urlencoded parser
855872
// Ref: https://url.spec.whatwg.org/#concept-urlencoded-parser
856873
function parseParams(qs) {
@@ -1341,6 +1358,7 @@ module.exports = {
13411358
pathToFileURL,
13421359
toPathIfFileURL,
13431360
isURLInstance,
1361+
installObjectURLMethods,
13441362
URL,
13451363
URLSearchParams,
13461364
domainToASCII,

lib/internal/util.js

+23
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,27 @@ function exposeInterface(target, name, interfaceObject) {
511511
});
512512
}
513513

514+
// https://heycam.github.io/webidl/#es-namespaces
515+
function exposeNamespace(target, name, namespaceObject) {
516+
ObjectDefineProperty(target, name, {
517+
__proto__: null,
518+
writable: true,
519+
enumerable: false,
520+
configurable: true,
521+
value: namespaceObject,
522+
});
523+
}
524+
525+
function exposeGetterAndSetter(target, name, getter, setter = undefined) {
526+
ObjectDefineProperty(target, name, {
527+
__proto__: null,
528+
enumerable: false,
529+
configurable: true,
530+
get: getter,
531+
set: setter,
532+
});
533+
}
534+
514535
function defineLazyProperties(target, id, keys, enumerable = true) {
515536
const descriptors = { __proto__: null };
516537
let mod;
@@ -750,6 +771,8 @@ module.exports = {
750771
emitExperimentalWarning,
751772
exposeInterface,
752773
exposeLazyInterfaces,
774+
exposeNamespace,
775+
exposeGetterAndSetter,
753776
filterDuplicateStrings,
754777
filterOwnProperties,
755778
getConstructorOf,

src/node_realm.cc

+4-3
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,10 @@ MaybeLocal<Value> Realm::BootstrapNode() {
218218
}
219219

220220
if (!env_->no_browser_globals()) {
221-
result = ExecuteBootstrapper("internal/bootstrap/browser");
222-
223-
if (result.IsEmpty()) {
221+
if (ExecuteBootstrapper("internal/bootstrap/web/exposed-wildcard")
222+
.IsEmpty() ||
223+
ExecuteBootstrapper("internal/bootstrap/web/exposed-window-or-worker")
224+
.IsEmpty()) {
224225
return MaybeLocal<Value>();
225226
}
226227
}

0 commit comments

Comments
 (0)