lib: make safe primordials safe to iterate
PR-URL: https://github.com/nodejs/node/pull/36391 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
7c808170f5
commit
0a5969c62a
@ -91,9 +91,52 @@ function copyPrototype(src, dest, prefix) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createSafeIterator = (factory, next) => {
|
||||||
|
class SafeIterator {
|
||||||
|
constructor(iterable) {
|
||||||
|
this._iterator = factory(iterable);
|
||||||
|
}
|
||||||
|
next() {
|
||||||
|
return next(this._iterator);
|
||||||
|
}
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object.setPrototypeOf(SafeIterator.prototype, null);
|
||||||
|
Object.freeze(SafeIterator.prototype);
|
||||||
|
Object.freeze(SafeIterator);
|
||||||
|
return SafeIterator;
|
||||||
|
};
|
||||||
|
|
||||||
function makeSafe(unsafe, safe) {
|
function makeSafe(unsafe, safe) {
|
||||||
copyProps(unsafe.prototype, safe.prototype);
|
if (Symbol.iterator in unsafe.prototype) {
|
||||||
|
const dummy = new unsafe();
|
||||||
|
let next; // We can reuse the same `next` method.
|
||||||
|
|
||||||
|
for (const key of Reflect.ownKeys(unsafe.prototype)) {
|
||||||
|
if (!Reflect.getOwnPropertyDescriptor(safe.prototype, key)) {
|
||||||
|
const desc = Reflect.getOwnPropertyDescriptor(unsafe.prototype, key);
|
||||||
|
if (
|
||||||
|
typeof desc.value === 'function' &&
|
||||||
|
desc.value.length === 0 &&
|
||||||
|
Symbol.iterator in (desc.value.call(dummy) ?? {})
|
||||||
|
) {
|
||||||
|
const createIterator = uncurryThis(desc.value);
|
||||||
|
next ??= uncurryThis(createIterator(dummy).next);
|
||||||
|
const SafeIterator = createSafeIterator(createIterator, next);
|
||||||
|
desc.value = function() {
|
||||||
|
return new SafeIterator(this);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Reflect.defineProperty(safe.prototype, key, desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
copyProps(unsafe.prototype, safe.prototype);
|
||||||
|
}
|
||||||
copyProps(unsafe, safe);
|
copyProps(unsafe, safe);
|
||||||
|
|
||||||
Object.setPrototypeOf(safe.prototype, null);
|
Object.setPrototypeOf(safe.prototype, null);
|
||||||
Object.freeze(safe.prototype);
|
Object.freeze(safe.prototype);
|
||||||
Object.freeze(safe);
|
Object.freeze(safe);
|
||||||
|
@ -7,17 +7,12 @@ const {
|
|||||||
ObjectKeys,
|
ObjectKeys,
|
||||||
ObjectGetOwnPropertyDescriptor,
|
ObjectGetOwnPropertyDescriptor,
|
||||||
ObjectPrototypeHasOwnProperty,
|
ObjectPrototypeHasOwnProperty,
|
||||||
Map,
|
|
||||||
MapPrototypeEntries,
|
|
||||||
RegExpPrototypeTest,
|
RegExpPrototypeTest,
|
||||||
SafeMap,
|
SafeMap,
|
||||||
StringPrototypeMatch,
|
StringPrototypeMatch,
|
||||||
StringPrototypeSplit,
|
StringPrototypeSplit,
|
||||||
uncurryThis,
|
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
const MapIteratorNext = uncurryThis(MapPrototypeEntries(new Map()).next);
|
|
||||||
|
|
||||||
function ObjectGetValueSafe(obj, key) {
|
function ObjectGetValueSafe(obj, key) {
|
||||||
const desc = ObjectGetOwnPropertyDescriptor(obj, key);
|
const desc = ObjectGetOwnPropertyDescriptor(obj, key);
|
||||||
return ObjectPrototypeHasOwnProperty(desc, 'value') ? desc.value : undefined;
|
return ObjectPrototypeHasOwnProperty(desc, 'value') ? desc.value : undefined;
|
||||||
@ -195,11 +190,7 @@ function rekeySourceMap(cjsModuleInstance, newInstance) {
|
|||||||
function sourceMapCacheToObject() {
|
function sourceMapCacheToObject() {
|
||||||
const obj = ObjectCreate(null);
|
const obj = ObjectCreate(null);
|
||||||
|
|
||||||
const it = MapPrototypeEntries(esmSourceMapCache);
|
for (const { 0: k, 1: v } of esmSourceMapCache) {
|
||||||
let entry;
|
|
||||||
while (!(entry = MapIteratorNext(it)).done) {
|
|
||||||
const k = entry.value[0];
|
|
||||||
const v = entry.value[1];
|
|
||||||
obj[k] = v;
|
obj[k] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
ArrayPrototypeForEach,
|
||||||
ArrayPrototypeMap,
|
ArrayPrototypeMap,
|
||||||
ArrayPrototypePush,
|
ArrayPrototypePush,
|
||||||
FunctionPrototypeBind,
|
FunctionPrototypeBind,
|
||||||
@ -315,8 +316,7 @@ class WritableWorkerStdio extends Writable {
|
|||||||
[kStdioWantsMoreDataCallback]() {
|
[kStdioWantsMoreDataCallback]() {
|
||||||
const cbs = this[kWritableCallbacks];
|
const cbs = this[kWritableCallbacks];
|
||||||
this[kWritableCallbacks] = [];
|
this[kWritableCallbacks] = [];
|
||||||
for (const cb of cbs)
|
ArrayPrototypeForEach(cbs, (cb) => cb());
|
||||||
cb();
|
|
||||||
if ((this[kPort][kWaitingStreams] -= cbs.length) === 0)
|
if ((this[kPort][kWaitingStreams] -= cbs.length) === 0)
|
||||||
this[kPort].unref();
|
this[kPort].unref();
|
||||||
}
|
}
|
||||||
|
@ -27,16 +27,19 @@ const { callCount } = workerData;
|
|||||||
function increaseCallCount() { callCount[0]++; }
|
function increaseCallCount() { callCount[0]++; }
|
||||||
|
|
||||||
// Increase the call count when a forbidden method is called.
|
// Increase the call count when a forbidden method is called.
|
||||||
Object.getPrototypeOf((new Map()).entries()).next = increaseCallCount;
|
|
||||||
Map.prototype.entries = increaseCallCount;
|
|
||||||
Object.keys = increaseCallCount;
|
|
||||||
Object.create = increaseCallCount;
|
|
||||||
Object.hasOwnProperty = increaseCallCount;
|
|
||||||
for (const property of ['_cache', 'lineLengths', 'url']) {
|
for (const property of ['_cache', 'lineLengths', 'url']) {
|
||||||
Object.defineProperty(Object.prototype, property, {
|
Object.defineProperty(Object.prototype, property, {
|
||||||
get: increaseCallCount,
|
get: increaseCallCount,
|
||||||
set: increaseCallCount
|
set: increaseCallCount
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Object.getPrototypeOf([][Symbol.iterator]()).next = increaseCallCount;
|
||||||
|
Object.getPrototypeOf((new Map()).entries()).next = increaseCallCount;
|
||||||
|
Array.prototype[Symbol.iterator] = increaseCallCount;
|
||||||
|
Map.prototype[Symbol.iterator] = increaseCallCount;
|
||||||
|
Map.prototype.entries = increaseCallCount;
|
||||||
|
Object.keys = increaseCallCount;
|
||||||
|
Object.create = increaseCallCount;
|
||||||
|
Object.hasOwnProperty = increaseCallCount;
|
||||||
|
|
||||||
parentPort.postMessage('done');
|
parentPort.postMessage('done');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user