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) {
|
||||
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);
|
||||
|
||||
Object.setPrototypeOf(safe.prototype, null);
|
||||
Object.freeze(safe.prototype);
|
||||
Object.freeze(safe);
|
||||
|
@ -7,17 +7,12 @@ const {
|
||||
ObjectKeys,
|
||||
ObjectGetOwnPropertyDescriptor,
|
||||
ObjectPrototypeHasOwnProperty,
|
||||
Map,
|
||||
MapPrototypeEntries,
|
||||
RegExpPrototypeTest,
|
||||
SafeMap,
|
||||
StringPrototypeMatch,
|
||||
StringPrototypeSplit,
|
||||
uncurryThis,
|
||||
} = primordials;
|
||||
|
||||
const MapIteratorNext = uncurryThis(MapPrototypeEntries(new Map()).next);
|
||||
|
||||
function ObjectGetValueSafe(obj, key) {
|
||||
const desc = ObjectGetOwnPropertyDescriptor(obj, key);
|
||||
return ObjectPrototypeHasOwnProperty(desc, 'value') ? desc.value : undefined;
|
||||
@ -195,11 +190,7 @@ function rekeySourceMap(cjsModuleInstance, newInstance) {
|
||||
function sourceMapCacheToObject() {
|
||||
const obj = ObjectCreate(null);
|
||||
|
||||
const it = MapPrototypeEntries(esmSourceMapCache);
|
||||
let entry;
|
||||
while (!(entry = MapIteratorNext(it)).done) {
|
||||
const k = entry.value[0];
|
||||
const v = entry.value[1];
|
||||
for (const { 0: k, 1: v } of esmSourceMapCache) {
|
||||
obj[k] = v;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
ArrayPrototypeForEach,
|
||||
ArrayPrototypeMap,
|
||||
ArrayPrototypePush,
|
||||
FunctionPrototypeBind,
|
||||
@ -315,8 +316,7 @@ class WritableWorkerStdio extends Writable {
|
||||
[kStdioWantsMoreDataCallback]() {
|
||||
const cbs = this[kWritableCallbacks];
|
||||
this[kWritableCallbacks] = [];
|
||||
for (const cb of cbs)
|
||||
cb();
|
||||
ArrayPrototypeForEach(cbs, (cb) => cb());
|
||||
if ((this[kPort][kWaitingStreams] -= cbs.length) === 0)
|
||||
this[kPort].unref();
|
||||
}
|
||||
|
@ -27,16 +27,19 @@ const { callCount } = workerData;
|
||||
function increaseCallCount() { callCount[0]++; }
|
||||
|
||||
// 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']) {
|
||||
Object.defineProperty(Object.prototype, property, {
|
||||
get: 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');
|
||||
|
Loading…
x
Reference in New Issue
Block a user