fix(core): Use safe primordials wrappers (#18687)

This commit is contained in:
Kenta Moriuchi 2023-04-15 05:23:28 +09:00 committed by GitHub
parent 136dce67ce
commit f086ec57b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 83 additions and 60 deletions

View file

@ -9,7 +9,6 @@
ArrayPrototypePush,
Error,
ErrorCaptureStackTrace,
Map,
MapPrototypeDelete,
MapPrototypeGet,
MapPrototypeHas,
@ -22,6 +21,7 @@
RangeError,
ReferenceError,
SafeArrayIterator,
SafeMap,
SafePromisePrototypeFinally,
setQueueMicrotask,
StringPrototypeSlice,
@ -65,7 +65,7 @@
registerErrorClass("URIError", URIError);
let nextPromiseId = 1;
const promiseMap = new Map();
const promiseMap = new SafeMap();
const RING_SIZE = 4 * 1024;
const NO_PROMISE = null; // Alias to null is faster than plain nulls
const promiseRing = ArrayPrototypeFill(new Array(RING_SIZE), NO_PROMISE);
@ -74,7 +74,7 @@
const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId");
let opCallTracingEnabled = false;
const opCallTraces = new Map();
const opCallTraces = new SafeMap();
function enableOpCallTracing() {
opCallTracingEnabled = true;

View file

@ -54,6 +54,7 @@ const {
RegExpPrototypeTest,
RegExpPrototypeToString,
SafeArrayIterator,
SafeMap,
SafeStringIterator,
SafeSet,
SafeRegExp,
@ -85,7 +86,6 @@ const {
ArrayPrototypeFind,
FunctionPrototypeBind,
FunctionPrototypeToString,
Map,
MapPrototype,
MapPrototypeHas,
MapPrototypeGet,
@ -658,7 +658,7 @@ let circular;
function handleCircular(value, cyan) {
let index = 1;
if (circular === undefined) {
circular = new Map();
circular = new SafeMap();
MapPrototypeSet(circular, value, index);
} else {
index = MapPrototypeGet(circular, value);
@ -1016,7 +1016,7 @@ function inspectError(value, cyan) {
}
}
const refMap = new Map();
const refMap = new SafeMap();
for (let i = 0; i < causes.length; ++i) {
const cause = causes[i];
if (circular !== undefined) {
@ -1405,7 +1405,7 @@ function inspectObject(value, inspectOptions, proxyDetails) {
}
}
const colorKeywords = new Map([
const colorKeywords = new SafeMap([
["black", "#000000"],
["silver", "#c0c0c0"],
["gray", "#808080"],
@ -1990,8 +1990,8 @@ function inspectArgs(args, inspectOptions = {}) {
return string;
}
const countMap = new Map();
const timerMap = new Map();
const countMap = new SafeMap();
const timerMap = new SafeMap();
const isConsoleInstance = Symbol("isConsoleInstance");
function getConsoleInspectOptions() {

View file

@ -33,6 +33,7 @@ const {
StringPrototypeCharCodeAt,
StringFromCharCode,
SafeArrayIterator,
SafeWeakMap,
Symbol,
SymbolFor,
SyntaxError,
@ -43,7 +44,6 @@ const {
TypedArrayPrototypeGetSymbolToStringTag,
TypeError,
Uint8Array,
WeakMap,
WeakMapPrototypeGet,
WeakMapPrototypeSet,
} = primordials;
@ -391,7 +391,7 @@ function usageIntersection(a, b) {
// TODO(lucacasonato): this should be moved to rust
/** @type {WeakMap<object, object>} */
const KEY_STORE = new WeakMap();
const KEY_STORE = new SafeWeakMap();
function getKeyLength(algorithm) {
switch (algorithm.name) {

View file

@ -22,12 +22,12 @@ const {
ArrayPrototypePush,
ArrayPrototypeSlice,
ArrayPrototypeSplice,
Map,
MapPrototypeGet,
MapPrototypeSet,
MathRandom,
ObjectFreeze,
ObjectPrototypeIsPrototypeOf,
SafeMap,
SafeRegExp,
Symbol,
StringFromCharCode,
@ -346,13 +346,15 @@ function formDataToBlob(formData) {
});
}
const QUOTE_CONTENT_PATTERN = new SafeRegExp(/^"([^"]*)"$/);
/**
* @param {string} value
* @returns {Map<string, string>}
*/
function parseContentDisposition(value) {
/** @type {Map<string, string>} */
const params = new Map();
const params = new SafeMap();
// Forced to do so for some Map constructor param mismatch
const values = ArrayPrototypeSlice(StringPrototypeSplit(value, ";"), 1);
for (let i = 0; i < values.length; i++) {
@ -361,7 +363,7 @@ function parseContentDisposition(value) {
MapPrototypeSet(
params,
entries[0],
StringPrototypeReplace(entries[1], /^"([^"]*)"$/, "$1"),
StringPrototypeReplace(entries[1], QUOTE_CONTENT_PATTERN, "$1"),
);
}
}

View file

@ -42,13 +42,13 @@ const {
PromisePrototypeThen,
PromisePrototypeCatch,
SafeArrayIterator,
SafeWeakMap,
String,
StringPrototypeStartsWith,
StringPrototypeToLowerCase,
TypeError,
Uint8Array,
Uint8ArrayPrototype,
WeakMap,
WeakMapPrototypeDelete,
WeakMapPrototypeGet,
WeakMapPrototypeHas,
@ -62,7 +62,7 @@ const REQUEST_BODY_HEADER_NAMES = [
"content-type",
];
const requestBodyReaders = new WeakMap();
const requestBodyReaders = new SafeWeakMap();
/**
* @param {{ method: string, url: string, headers: [string, string][], clientRid: number | null, hasBody: boolean }} args

View file

@ -30,8 +30,8 @@ const {
MathCeil,
SafeMap,
SafeArrayIterator,
SafeWeakMap,
SymbolFor,
WeakMap,
} = primordials;
import { pathFromURL } from "ext:deno_web/00_infra.js";
@ -204,7 +204,7 @@ const OUT_BUFFER = new Uint32Array(2);
const OUT_BUFFER_64 = new BigInt64Array(
TypedArrayPrototypeGetBuffer(OUT_BUFFER),
);
const POINTER_TO_BUFFER_WEAK_MAP = new WeakMap();
const POINTER_TO_BUFFER_WEAK_MAP = new SafeWeakMap();
class UnsafePointer {
static create(value) {
return ops.op_ffi_ptr_create(value);

View file

@ -47,8 +47,9 @@ const {
ArrayPrototypePush,
Error,
ObjectPrototypeIsPrototypeOf,
PromisePrototypeCatch,
SafeSet,
SafeSetIterator,
Set,
SetPrototypeAdd,
SetPrototypeDelete,
SetPrototypeClear,
@ -56,8 +57,6 @@ const {
StringPrototypeIncludes,
StringPrototypeToLowerCase,
StringPrototypeSplit,
SafeSet,
PromisePrototypeCatch,
Symbol,
SymbolAsyncIterator,
TypeError,
@ -79,7 +78,7 @@ class HttpConn {
// that were created during lifecycle of this request.
// When the connection is closed these resources should be closed
// as well.
managedResources = new Set();
managedResources = new SafeSet();
constructor(rid, remoteAddr, localAddr) {
this.#rid = rid;

View file

@ -18,6 +18,7 @@ const {
JSONStringify,
NumberPrototypeToString,
ObjectPrototypeIsPrototypeOf,
RegExpPrototypeTest,
SafeArrayIterator,
SafeRegExp,
String,
@ -26,6 +27,7 @@ const {
StringPrototypeMatch,
StringPrototypePadStart,
StringPrototypeReplace,
StringPrototypeReplaceAll,
StringPrototypeSlice,
StringPrototypeSubstring,
StringPrototypeToLowerCase,
@ -274,17 +276,24 @@ function addPaddingToBase64url(base64url) {
return base64url;
}
const BASE64URL_PATTERN = new SafeRegExp(/^[-_A-Z0-9]*?={0,2}$/i);
/**
* @param {string} base64url
* @returns {string}
*/
function convertBase64urlToBase64(base64url) {
if (!/^[-_A-Z0-9]*?={0,2}$/i.test(base64url)) {
if (!RegExpPrototypeTest(BASE64URL_PATTERN, base64url)) {
// Contains characters not part of base64url spec.
throw new TypeError("Failed to decode base64url: invalid character");
}
return addPaddingToBase64url(base64url).replace(/\-/g, "+").replace(
/_/g,
return StringPrototypeReplaceAll(
StringPrototypeReplaceAll(
addPaddingToBase64url(base64url),
"-",
"+",
),
"_",
"/",
);
}
@ -295,9 +304,21 @@ function convertBase64urlToBase64(base64url) {
* @returns {string}
*/
function forgivingBase64UrlEncode(data) {
return forgivingBase64Encode(
typeof data === "string" ? new TextEncoder().encode(data) : data,
).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
return StringPrototypeReplaceAll(
StringPrototypeReplaceAll(
StringPrototypeReplaceAll(
forgivingBase64Encode(
typeof data === "string" ? new TextEncoder().encode(data) : data,
),
"=",
"",
),
"+",
"-",
),
"/",
"_",
);
}
/**

View file

@ -9,11 +9,11 @@
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeIncludes,
Map,
MapPrototypeGet,
MapPrototypeHas,
MapPrototypeSet,
RegExpPrototypeTest,
SafeMap,
SafeMapIterator,
StringPrototypeReplaceAll,
StringPrototypeToLowerCase,
@ -92,7 +92,7 @@ function parseMimeType(input) {
type: StringPrototypeToLowerCase(type),
subtype: StringPrototypeToLowerCase(subtype),
/** @type {Map<string, string>} */
parameters: new Map(),
parameters: new SafeMap(),
};
// 11.

View file

@ -24,7 +24,6 @@ const {
DateNow,
Error,
FunctionPrototypeCall,
Map,
MapPrototypeGet,
MapPrototypeSet,
ObjectCreate,
@ -34,6 +33,7 @@ const {
ReflectDefineProperty,
ReflectHas,
SafeArrayIterator,
SafeMap,
StringPrototypeStartsWith,
Symbol,
SymbolFor,
@ -1443,7 +1443,7 @@ function defineEventHandler(
}
if (!this[_eventHandlers]) {
this[_eventHandlers] = new Map();
this[_eventHandlers] = new SafeMap();
}
let handlerWrapper = MapPrototypeGet(this[_eventHandlers], name);
if (handlerWrapper) {

View file

@ -20,12 +20,12 @@ const {
DataViewPrototypeGetByteLength,
DataViewPrototypeGetByteOffset,
ObjectPrototypeIsPrototypeOf,
SafeWeakMap,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteOffset,
TypedArrayPrototypeGetLength,
TypedArrayPrototypeGetSymbolToStringTag,
TypeErrorPrototype,
WeakMap,
WeakMapPrototypeSet,
Int8Array,
Int16Array,
@ -40,7 +40,7 @@ const {
Float64Array,
} = primordials;
const objectCloneMemo = new WeakMap();
const objectCloneMemo = new SafeWeakMap();
function cloneArrayBuffer(
srcBuffer,

View file

@ -7,7 +7,6 @@ const {
ArrayPrototypePush,
ArrayPrototypeShift,
FunctionPrototypeCall,
Map,
MapPrototypeDelete,
MapPrototypeGet,
MapPrototypeHas,
@ -18,6 +17,7 @@ const {
NumberPOSITIVE_INFINITY,
PromisePrototypeThen,
SafeArrayIterator,
SafeMap,
SymbolFor,
TypedArrayPrototypeGetBuffer,
TypeError,
@ -76,7 +76,7 @@ function handleTimerMacrotask() {
*
* @type {Map<number, { cancelRid: number, isRef: boolean, promiseId: number }>}
*/
const activeTimers = new Map();
const activeTimers = new SafeMap();
let nextId = 1;

View file

@ -14,8 +14,8 @@ import {
const primordials = globalThis.__bootstrap.primordials;
const {
SafeArrayIterator,
SafeSet,
SafeSetIterator,
Set,
SetPrototypeAdd,
SetPrototypeDelete,
Symbol,
@ -69,7 +69,7 @@ class AbortSignal extends EventTarget {
return;
}
if (this[abortAlgos] === null) {
this[abortAlgos] = new Set();
this[abortAlgos] = new SafeSet();
}
SetPrototypeAdd(this[abortAlgos], algorithm);
}

View file

@ -34,7 +34,6 @@ const {
DataViewPrototypeGetByteOffset,
Float32Array,
Float64Array,
FinalizationRegistry,
Int8Array,
Int16Array,
Int32Array,
@ -56,7 +55,9 @@ const {
queueMicrotask,
RangeError,
ReflectHas,
SafeFinalizationRegistry,
SafePromiseAll,
SafeWeakMap,
// TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBufferPrototype
Symbol,
@ -73,7 +74,6 @@ const {
Uint16Array,
Uint32Array,
Uint8ClampedArray,
WeakMap,
WeakMapPrototypeGet,
WeakMapPrototypeHas,
WeakMapPrototypeSet,
@ -695,7 +695,7 @@ function isReadableStreamDisturbed(stream) {
const DEFAULT_CHUNK_SIZE = 64 * 1024; // 64 KiB
// A finalization registry to clean up underlying resources that are GC'ed.
const RESOURCE_REGISTRY = new FinalizationRegistry((rid) => {
const RESOURCE_REGISTRY = new SafeFinalizationRegistry((rid) => {
core.tryClose(rid);
});
@ -4743,7 +4743,7 @@ webidl.configurePrototype(ByteLengthQueuingStrategy);
const ByteLengthQueuingStrategyPrototype = ByteLengthQueuingStrategy.prototype;
/** @type {WeakMap<typeof globalThis, (chunk: ArrayBufferView) => number>} */
const byteSizeFunctionWeakMap = new WeakMap();
const byteSizeFunctionWeakMap = new SafeWeakMap();
function initializeByteLengthSizeFunction(globalObject) {
if (WeakMapPrototypeHas(byteSizeFunctionWeakMap, globalObject)) {
@ -4800,7 +4800,7 @@ webidl.configurePrototype(CountQueuingStrategy);
const CountQueuingStrategyPrototype = CountQueuingStrategy.prototype;
/** @type {WeakMap<typeof globalThis, () => 1>} */
const countSizeFunctionWeakMap = new WeakMap();
const countSizeFunctionWeakMap = new SafeWeakMap();
/** @param {typeof globalThis} globalObject */
function initializeCountSizeFunction(globalObject) {

View file

@ -27,13 +27,13 @@ const {
DataViewPrototypeGetByteOffset,
Date,
DatePrototypeGetTime,
FinalizationRegistry,
MathMax,
MathMin,
ObjectPrototypeIsPrototypeOf,
RegExpPrototypeTest,
// TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBufferPrototype
SafeFinalizationRegistry,
SafeRegExp,
StringPrototypeCharAt,
StringPrototypeToLowerCase,
@ -549,7 +549,7 @@ webidl.converters["FilePropertyBag"] = webidl.createDictionaryConverter(
// A finalization registry to deallocate a blob part when its JS reference is
// garbage collected.
const registry = new FinalizationRegistry((uuid) => {
const registry = new SafeFinalizationRegistry((uuid) => {
ops.op_blob_remove_part(uuid);
});

View file

@ -23,12 +23,12 @@ const {
ArrayPrototypePush,
ArrayPrototypeReduce,
FunctionPrototypeCall,
Map,
MapPrototypeGet,
MapPrototypeSet,
ObjectDefineProperty,
queueMicrotask,
SafeArrayIterator,
SafeMap,
Symbol,
TypedArrayPrototypeSet,
TypedArrayPrototypeGetBuffer,
@ -273,7 +273,7 @@ class FileReader extends EventTarget {
webidl.assertBranded(this, FileReaderPrototype);
if (!this[handlerSymbol]) {
this[handlerSymbol] = new Map();
this[handlerSymbol] = new SafeMap();
}
let handlerWrapper = MapPrototypeGet(this[handlerSymbol], name);
if (handlerWrapper) {

View file

@ -8,11 +8,11 @@ const primordials = globalThis.__bootstrap.primordials;
const {
Error,
ObjectDefineProperties,
SafeWeakMap,
Symbol,
SymbolFor,
SymbolToStringTag,
TypeError,
WeakMap,
WeakMapPrototypeGet,
WeakMapPrototypeSet,
} = primordials;
@ -206,7 +206,7 @@ ObjectDefineProperties(Location.prototype, {
},
});
const workerLocationUrls = new WeakMap();
const workerLocationUrls = new SafeWeakMap();
class WorkerLocation {
constructor(href = null, key = null) {

View file

@ -60,7 +60,7 @@ const {
ReflectOwnKeys,
RegExpPrototypeTest,
SafeRegExp,
Set,
SafeSet,
SetPrototypeEntries,
SetPrototypeForEach,
SetPrototypeKeys,
@ -752,7 +752,7 @@ function createDictionaryConverter(name, ...dictionaries) {
// https://heycam.github.io/webidl/#es-enumeration
function createEnumConverter(name, values) {
const E = new Set(values);
const E = new SafeSet(values);
return function (V, opts = {}) {
const S = String(V);

View file

@ -33,7 +33,7 @@ const {
ObjectPrototypeIsPrototypeOf,
PromisePrototypeThen,
RegExpPrototypeTest,
Set,
SafeSet,
SetPrototypeGetSize,
// TODO(lucacasonato): add SharedArrayBuffer to primordials
// SharedArrayBufferPrototype
@ -223,7 +223,7 @@ class WebSocket extends EventTarget {
if (
protocols.length !==
SetPrototypeGetSize(
new Set(
new SafeSet(
ArrayPrototypeMap(protocols, (p) => StringPrototypeToLowerCase(p)),
),
)

View file

@ -21,7 +21,7 @@ const {
ObjectPrototypeIsPrototypeOf,
PromisePrototypeCatch,
PromisePrototypeThen,
Set,
SafeSet,
SetPrototypeGetSize,
StringPrototypeEndsWith,
StringPrototypeToLowerCase,
@ -118,7 +118,7 @@ class WebSocketStream {
if (
options.protocols.length !==
SetPrototypeGetSize(
new Set(
new SafeSet(
ArrayPrototypeMap(
options.protocols,
(p) => StringPrototypeToLowerCase(p),

View file

@ -10,7 +10,6 @@ const {
ArrayPrototypeIncludes,
ArrayPrototypeMap,
ArrayPrototypeSlice,
Map,
MapPrototypeGet,
MapPrototypeHas,
MapPrototypeSet,
@ -19,6 +18,7 @@ const {
PromiseReject,
ReflectHas,
SafeArrayIterator,
SafeMap,
Symbol,
SymbolFor,
TypeError,
@ -113,7 +113,7 @@ class PermissionStatus extends EventTarget {
}
/** @type {Map<string, StatusCacheValue>} */
const statusCache = new Map();
const statusCache = new SafeMap();
/**
* @param {Deno.PermissionDescriptor} desc

View file

@ -4,8 +4,9 @@ const core = globalThis.Deno.core;
const ops = core.ops;
const primordials = globalThis.__bootstrap.primordials;
const {
SafeSet,
SafeSetIterator,
Set,
SetPrototypeAdd,
SetPrototypeDelete,
SymbolFor,
TypeError,
@ -32,7 +33,7 @@ const signalData = {};
/** Gets the signal handlers and resource data of the given signal */
function getSignalData(signo) {
return signalData[signo] ??
(signalData[signo] = { rid: undefined, listeners: new Set() });
(signalData[signo] = { rid: undefined, listeners: new SafeSet() });
}
function checkSignalListenerType(listener) {
@ -47,7 +48,7 @@ function addSignalListener(signo, listener) {
checkSignalListenerType(listener);
const sigData = getSignalData(signo);
sigData.listeners.add(listener);
SetPrototypeAdd(sigData.listeners, listener);
if (!sigData.rid) {
// If signal resource doesn't exist, create it.