fix(runtime): use more null proto objects (#23921)

This is a primordialization effort to improve resistance against users
tampering with the global `Object` prototype.

---------

Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
Luca Casonato 2024-05-23 00:03:35 +02:00 committed by GitHub
parent 6c167c64d6
commit 971f09abe4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 141 additions and 92 deletions

View File

@ -342,7 +342,7 @@ function enableJupyter() {
async function broadcast(
msgType,
content,
{ metadata = {}, buffers = [] } = {},
{ metadata = { __proto__: null }, buffers = [] } = { __proto__: null },
) {
await op_jupyter_broadcast(msgType, content, metadata, buffers);
}
@ -400,7 +400,7 @@ function enableJupyter() {
if (options.update) {
messageType = "update_display_data";
}
let transient = {};
let transient = { __proto__: null };
if (options.display_id) {
transient = { display_id: options.display_id };
}

View File

@ -196,7 +196,7 @@ function testInner(
nameOrFnOrOptions,
optionsOrFn,
maybeFn,
overrides = {},
overrides = { __proto__: null },
) {
// No-op if we're not running in `deno test` subcommand.
if (typeof op_register_test !== "function") {

View File

@ -2930,7 +2930,7 @@ function cssToAnsi(css, prevCss = null) {
return ansi;
}
function inspectArgs(args, inspectOptions = {}) {
function inspectArgs(args, inspectOptions = { __proto__: null }) {
const ctx = {
...getDefaultInspectOptions(),
colors: inspectOptions.colors ?? !noColorStdout(),
@ -3124,7 +3124,7 @@ class Console {
);
};
dir = (obj = undefined, options = {}) => {
dir = (obj = undefined, options = { __proto__: null }) => {
this.#printFunc(
inspectArgs([obj], {
...getConsoleInspectOptions(noColorStdout()),
@ -3232,7 +3232,7 @@ class Console {
resultData = [...new SafeSetIterator(data)];
} else if (isMapObject) {
let idx = 0;
resultData = {};
resultData = { __proto__: null };
MapPrototypeForEach(data, (v, k) => {
resultData[idx] = { Key: k, Values: v };
@ -3390,7 +3390,7 @@ const customInspect = SymbolFor("Deno.customInspect");
function inspect(
value,
inspectOptions = {},
inspectOptions = { __proto__: null },
) {
// Default options
const ctx = {

View File

@ -100,7 +100,7 @@ function checkForInvalidValueChars(value) {
return true;
}
let HEADER_NAME_CACHE = {};
let HEADER_NAME_CACHE = { __proto__: null };
let HEADER_CACHE_SIZE = 0;
const HEADER_NAME_CACHE_SIZE_BOUNDARY = 4096;
function checkHeaderNameForHttpTokenCodePoint(name) {
@ -112,7 +112,7 @@ function checkHeaderNameForHttpTokenCodePoint(name) {
const valid = RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, name);
if (HEADER_CACHE_SIZE > HEADER_NAME_CACHE_SIZE_BOUNDARY) {
HEADER_NAME_CACHE = {};
HEADER_NAME_CACHE = { __proto__: null };
HEADER_CACHE_SIZE = 0;
}
HEADER_CACHE_SIZE++;
@ -241,7 +241,7 @@ class Headers {
// The order of steps are not similar to the ones suggested by the
// spec but produce the same result.
const seenHeaders = {};
const seenHeaders = { __proto__: null };
const entries = [];
for (let i = 0; i < list.length; ++i) {
const entry = list[i];

View File

@ -300,7 +300,7 @@ class Request {
* @param {RequestInfo} input
* @param {RequestInit} init
*/
constructor(input, init = {}) {
constructor(input, init = { __proto__: null }) {
if (input === _brand) {
this[_brand] = _brand;
return;

View File

@ -282,7 +282,7 @@ class Response {
* @param {ResponseInit} init
* @returns {Response}
*/
static json(data = undefined, init = {}) {
static json(data = undefined, init = { __proto__: null }) {
const prefix = "Failed to execute 'Response.json'";
data = webidl.converters.any(data);
init = webidl.converters["ResponseInit_fast"](init, prefix, "Argument 2");

View File

@ -305,7 +305,7 @@ function httpRedirectFetch(request, response, terminator) {
* @param {RequestInfo} input
* @param {RequestInit} init
*/
function fetch(input, init = {}) {
function fetch(input, init = { __proto__: null }) {
// There is an async dispatch later that causes a stack trace disconnect.
// We reconnect it by assigning the result of that dispatch to `opPromise`,
// awaiting `opPromise` in an inner function also named `fetch()` and

View File

@ -144,7 +144,7 @@ class EventSource extends EventTarget {
return this.#withCredentials;
}
constructor(url, eventSourceInitDict = {}) {
constructor(url, eventSourceInitDict = { __proto__: null }) {
super();
this[webidl.brand] = webidl.brand;
const prefix = "Failed to construct 'EventSource'";

View File

@ -475,7 +475,7 @@ const UnsafeCallbackPrototype = UnsafeCallback.prototype;
class DynamicLibrary {
#rid;
symbols = {};
symbols = { __proto__: null };
constructor(path, symbols) {
({ 0: this.#rid, 1: this.symbols } = op_ffi_load({ path, symbols }));

View File

@ -155,7 +155,7 @@ function chdir(directory) {
op_fs_chdir(pathFromURL(directory));
}
function makeTempDirSync(options = {}) {
function makeTempDirSync(options = { __proto__: null }) {
return op_fs_make_temp_dir_sync(
options.dir,
options.prefix,
@ -163,7 +163,7 @@ function makeTempDirSync(options = {}) {
);
}
function makeTempDir(options = {}) {
function makeTempDir(options = { __proto__: null }) {
return op_fs_make_temp_dir_async(
options.dir,
options.prefix,
@ -171,7 +171,7 @@ function makeTempDir(options = {}) {
);
}
function makeTempFileSync(options = {}) {
function makeTempFileSync(options = { __proto__: null }) {
return op_fs_make_temp_file_sync(
options.dir,
options.prefix,
@ -179,7 +179,7 @@ function makeTempFileSync(options = {}) {
);
}
function makeTempFile(options = {}) {
function makeTempFile(options = { __proto__: null }) {
return op_fs_make_temp_file_async(
options.dir,
options.prefix,
@ -241,7 +241,7 @@ function realPath(path) {
function removeSync(
path,
options = {},
options = { __proto__: null },
) {
op_fs_remove_sync(
pathFromURL(path),
@ -251,7 +251,7 @@ function removeSync(
async function remove(
path,
options = {},
options = { __proto__: null },
) {
await op_fs_remove_async(
pathFromURL(path),
@ -773,7 +773,7 @@ class FsFile {
return core.isTerminal(this.#rid);
}
setRaw(mode, options = {}) {
setRaw(mode, options = { __proto__: null }) {
const cbreak = !!(options.cbreak ?? false);
op_set_raw(this.#rid, mode, cbreak);
}
@ -889,7 +889,7 @@ async function readTextFile(path, options) {
function writeFileSync(
path,
data,
options = {},
options = { __proto__: null },
) {
options.signal?.throwIfAborted();
op_fs_write_file_sync(
@ -905,7 +905,7 @@ function writeFileSync(
async function writeFile(
path,
data,
options = {},
options = { __proto__: null },
) {
let cancelRid;
let abortHandler;
@ -951,7 +951,7 @@ async function writeFile(
function writeTextFileSync(
path,
data,
options = {},
options = { __proto__: null },
) {
const encoder = new TextEncoder();
return writeFileSync(path, encoder.encode(data), options);
@ -960,7 +960,7 @@ function writeTextFileSync(
function writeTextFile(
path,
data,
options = {},
options = { __proto__: null },
) {
if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, data)) {
return writeFile(

View File

@ -591,7 +591,7 @@ function serve(arg1, arg2) {
throw new TypeError("A handler function must be provided.");
}
if (options === undefined) {
options = {};
options = { __proto__: null };
}
const wantsHttps = hasTlsKeyPairOptions(options);

View File

@ -37,7 +37,7 @@ const _ws = Symbol("[[associated_ws]]");
const websocketCvf = buildCaseInsensitiveCommaValueFinder("websocket");
const upgradeCvf = buildCaseInsensitiveCommaValueFinder("upgrade");
function upgradeWebSocket(request, options = {}) {
function upgradeWebSocket(request, options = { __proto__: null }) {
const inner = toInnerRequest(request);
const upgrade = request.headers.get("upgrade");
const upgradeHasWebSocketOption = upgrade !== null &&

View File

@ -228,7 +228,7 @@ class Stdin {
return this.#readable;
}
setRaw(mode, options = {}) {
setRaw(mode, options = { __proto__: null }) {
const cbreak = !!(options.cbreak ?? false);
op_set_raw(this.#rid, mode, cbreak);
}

View File

@ -210,7 +210,7 @@ class Kv {
cursor?: string;
reverse?: boolean;
consistency?: Deno.KvConsistencyLevel;
} = {},
} = { __proto__: null },
): KvListIterator {
if (options.limit !== undefined && options.limit <= 0) {
throw new Error("limit must be positive");
@ -340,7 +340,7 @@ class Kv {
finishMessageOps.clear();
}
watch(keys: Deno.KvKey[], options = {}) {
watch(keys: Deno.KvKey[], options = { __proto__: null }) {
const raw = options.raw ?? false;
const rid = op_kv_watch(this.#rid, keys);
const lastEntries: (Deno.KvEntryMaybe<unknown> | undefined)[] = ArrayFrom(

View File

@ -281,7 +281,7 @@ async function startTls(
hostname = "127.0.0.1",
caCerts = [],
alpnProtocols = undefined,
} = {},
} = { __proto__: null },
) {
const { 0: rid, 1: localAddr, 2: remoteAddr } = op_tls_start({
rid: conn[internalRidSymbol],

View File

@ -123,7 +123,7 @@ const _isTrusted = Symbol("[[isTrusted]]");
const _path = Symbol("[[path]]");
class Event {
constructor(type, eventInitDict = {}) {
constructor(type, eventInitDict = { __proto__: null }) {
// TODO(lucacasonato): remove when this interface is spec aligned
this[SymbolToStringTag] = "Event";
this[_canceledFlag] = false;
@ -1095,7 +1095,7 @@ class ErrorEvent extends Event {
lineno = 0,
colno = 0,
error,
} = {},
} = { __proto__: null },
) {
super(type, {
bubbles: bubbles,
@ -1164,7 +1164,7 @@ class CloseEvent extends Event {
wasClean = false,
code = 0,
reason = "",
} = {}) {
} = { __proto__: null }) {
super(type, {
bubbles: bubbles,
cancelable: cancelable,
@ -1238,7 +1238,7 @@ const MessageEventPrototype = MessageEvent.prototype;
class CustomEvent extends Event {
#detail = null;
constructor(type, eventInitDict = {}) {
constructor(type, eventInitDict = { __proto__: null }) {
super(type, eventInitDict);
webidl.requiredArguments(
arguments.length,
@ -1280,7 +1280,7 @@ ReflectDefineProperty(CustomEvent.prototype, "detail", {
// ProgressEvent could also be used in other DOM progress event emits.
// Current use is for FileReader.
class ProgressEvent extends Event {
constructor(type, eventInitDict = {}) {
constructor(type, eventInitDict = { __proto__: null }) {
super(type, eventInitDict);
this.lengthComputable = eventInitDict?.lengthComputable ?? false;
@ -1329,7 +1329,7 @@ class PromiseRejectionEvent extends Event {
composed,
promise,
reason,
} = {},
} = { __proto__: null },
) {
super(type, {
bubbles: bubbles,

View File

@ -5274,7 +5274,7 @@ class ReadableStream {
"Argument 1",
);
} else {
options = {};
options = { __proto__: null };
}
if (options.mode === undefined) {
return acquireReadableStreamDefaultReader(this);
@ -5290,7 +5290,7 @@ class ReadableStream {
* @param {PipeOptions=} options
* @returns {ReadableStream<T>}
*/
pipeThrough(transform, options = {}) {
pipeThrough(transform, options = { __proto__: null }) {
webidl.assertBranded(this, ReadableStreamPrototype);
const prefix = "Failed to execute 'pipeThrough' on 'ReadableStream'";
webidl.requiredArguments(arguments.length, 1, prefix);
@ -5329,7 +5329,7 @@ class ReadableStream {
* @param {PipeOptions=} options
* @returns {Promise<void>}
*/
pipeTo(destination, options = {}) {
pipeTo(destination, options = { __proto__: null }) {
try {
webidl.assertBranded(this, ReadableStreamPrototype);
const prefix = "Failed to execute 'pipeTo' on 'ReadableStream'";
@ -5567,7 +5567,7 @@ class ReadableStreamBYOBReader {
* @param {ReadableStreamBYOBReaderReadOptions} options
* @returns {Promise<ReadableStreamBYOBReadResult>}
*/
read(view, options = {}) {
read(view, options = { __proto__: null }) {
try {
webidl.assertBranded(this, ReadableStreamBYOBReaderPrototype);
const prefix = "Failed to execute 'read' on 'ReadableStreamBYOBReader'";
@ -6151,8 +6151,8 @@ class TransformStream {
*/
constructor(
transformer = undefined,
writableStrategy = {},
readableStrategy = {},
writableStrategy = { __proto__: null },
readableStrategy = { __proto__: null },
) {
const prefix = "Failed to construct 'TransformStream'";
if (transformer !== undefined) {

View File

@ -63,7 +63,7 @@ class TextDecoder {
* @param {string} label
* @param {TextDecoderOptions} options
*/
constructor(label = "utf-8", options = {}) {
constructor(label = "utf-8", options = { __proto__: null }) {
const prefix = "Failed to construct 'TextDecoder'";
label = webidl.converters.DOMString(label, prefix, "Argument 1");
options = webidl.converters.TextDecoderOptions(
@ -288,7 +288,7 @@ class TextDecoderStream {
* @param {string} label
* @param {TextDecoderOptions} options
*/
constructor(label = "utf-8", options = {}) {
constructor(label = "utf-8", options = { __proto__: null }) {
const prefix = "Failed to construct 'TextDecoderStream'";
label = webidl.converters.DOMString(label, prefix, "Argument 1");
options = webidl.converters.TextDecoderOptions(

View File

@ -223,7 +223,7 @@ class Blob {
* @param {BlobPart[]} blobParts
* @param {BlobPropertyBag} options
*/
constructor(blobParts = [], options = {}) {
constructor(blobParts = [], options = { __proto__: null }) {
const prefix = "Failed to construct 'Blob'";
blobParts = webidl.converters["sequence<BlobPart>"](
blobParts,
@ -500,7 +500,7 @@ class File extends Blob {
* @param {string} fileName
* @param {FilePropertyBag} options
*/
constructor(fileBits, fileName, options = {}) {
constructor(fileBits, fileName, options = { __proto__: null }) {
const prefix = "Failed to construct 'File'";
webidl.requiredArguments(arguments.length, 2, prefix);

View File

@ -150,7 +150,7 @@ class MessagePort extends EventTarget {
* @param {any} message
* @param {object[] | StructuredSerializeOptions} transferOrOptions
*/
postMessage(message, transferOrOptions = {}) {
postMessage(message, transferOrOptions = { __proto__: null }) {
webidl.assertBranded(this, MessagePortPrototype);
const prefix = "Failed to execute 'postMessage' on 'MessagePort'";
webidl.requiredArguments(arguments.length, 1, prefix);

View File

@ -234,7 +234,7 @@ class PerformanceMark extends PerformanceEntry {
constructor(
name,
options = {},
options = { __proto__: null },
) {
const prefix = "Failed to construct 'PerformanceMark'";
webidl.requiredArguments(arguments.length, 1, prefix);
@ -441,7 +441,7 @@ class Performance extends EventTarget {
mark(
markName,
markOptions = {},
markOptions = { __proto__: null },
) {
webidl.assertBranded(this, PerformancePrototype);
const prefix = "Failed to execute 'mark' on 'Performance'";
@ -466,7 +466,7 @@ class Performance extends EventTarget {
measure(
measureName,
startOrMeasureOptions = {},
startOrMeasureOptions = { __proto__: null },
endMark = undefined,
) {
webidl.assertBranded(this, PerformancePrototype);

View File

@ -358,7 +358,7 @@ class GPU {
* @param {GPURequestAdapterOptions} options
*/
// deno-lint-ignore require-await
async requestAdapter(options = {}) {
async requestAdapter(options = { __proto__: null }) {
webidl.assertBranded(this, GPUPrototype);
options = webidl.converters.GPURequestAdapterOptions(
options,
@ -449,7 +449,7 @@ class GPUAdapter {
* @returns {Promise<GPUDevice>}
*/
// deno-lint-ignore require-await
async requestDevice(descriptor = {}) {
async requestDevice(descriptor = { __proto__: null }) {
webidl.assertBranded(this, GPUAdapterPrototype);
const prefix = "Failed to execute 'requestDevice' on 'GPUAdapter'";
descriptor = webidl.converters.GPUDeviceDescriptor(
@ -1174,7 +1174,7 @@ class GPUDevice extends EventTarget {
* @param {GPUSamplerDescriptor} descriptor
* @returns {GPUSampler}
*/
createSampler(descriptor = {}) {
createSampler(descriptor = { __proto__: null }) {
webidl.assertBranded(this, GPUDevicePrototype);
const prefix = "Failed to execute 'createSampler' on 'GPUDevice'";
descriptor = webidl.converters.GPUSamplerDescriptor(
@ -1687,7 +1687,7 @@ class GPUDevice extends EventTarget {
* @param {GPUCommandEncoderDescriptor} descriptor
* @returns {GPUCommandEncoder}
*/
createCommandEncoder(descriptor = {}) {
createCommandEncoder(descriptor = { __proto__: null }) {
webidl.assertBranded(this, GPUDevicePrototype);
const prefix = "Failed to execute 'createCommandEncoder' on 'GPUDevice'";
descriptor = webidl.converters.GPUCommandEncoderDescriptor(
@ -1842,7 +1842,7 @@ defineEventHandler(GPUDevice.prototype, "uncapturederror");
class GPUPipelineError extends DOMException {
#reason;
constructor(message = "", options = {}) {
constructor(message = "", options = { __proto__: null }) {
const prefix = "Failed to construct 'GPUPipelineError'";
message = webidl.converters.DOMString(message, prefix, "Argument 1");
options = webidl.converters.GPUPipelineErrorInit(
@ -2499,7 +2499,7 @@ class GPUTexture {
/**
* @param {GPUTextureViewDescriptor} descriptor
*/
createView(descriptor = {}) {
createView(descriptor = { __proto__: null }) {
webidl.assertBranded(this, GPUTexturePrototype);
const prefix = "Failed to execute 'createView' on 'GPUTexture'";
webidl.requiredArguments(arguments.length, 0, prefix);
@ -3306,7 +3306,7 @@ class GPUCommandEncoder {
/**
* @param {GPUComputePassDescriptor} descriptor
*/
beginComputePass(descriptor = {}) {
beginComputePass(descriptor = { __proto__: null }) {
webidl.assertBranded(this, GPUCommandEncoderPrototype);
const prefix =
"Failed to execute 'beginComputePass' on 'GPUCommandEncoder'";
@ -3757,7 +3757,7 @@ class GPUCommandEncoder {
* @param {GPUCommandBufferDescriptor} descriptor
* @returns {GPUCommandBuffer}
*/
finish(descriptor = {}) {
finish(descriptor = { __proto__: null }) {
webidl.assertBranded(this, GPUCommandEncoderPrototype);
const prefix = "Failed to execute 'finish' on 'GPUCommandEncoder'";
descriptor = webidl.converters.GPUCommandBufferDescriptor(
@ -4774,7 +4774,7 @@ class GPURenderBundleEncoder {
/**
* @param {GPURenderBundleDescriptor} descriptor
*/
finish(descriptor = {}) {
finish(descriptor = { __proto__: null }) {
webidl.assertBranded(this, GPURenderBundleEncoderPrototype);
const prefix = "Failed to execute 'finish' on 'GPURenderBundleEncoder'";
descriptor = webidl.converters.GPURenderBundleDescriptor(

View File

@ -192,7 +192,12 @@ function createIntegerConversion(bitLength, typeOpts) {
const twoToTheBitLength = MathPow(2, bitLength);
const twoToOneLessThanTheBitLength = MathPow(2, bitLength - 1);
return (V, prefix = undefined, context = undefined, opts = {}) => {
return (
V,
prefix = undefined,
context = undefined,
opts = { __proto__: null },
) => {
let x = toNumber(V);
x = censorNegativeZero(x);
@ -251,7 +256,12 @@ function createLongLongConversion(bitLength, { unsigned }) {
const lowerBound = unsigned ? 0 : NumberMIN_SAFE_INTEGER;
const asBigIntN = unsigned ? BigIntAsUintN : BigIntAsIntN;
return (V, prefix = undefined, context = undefined, opts = {}) => {
return (
V,
prefix = undefined,
context = undefined,
opts = { __proto__: null },
) => {
let x = toNumber(V);
x = censorNegativeZero(x);
@ -386,7 +396,12 @@ converters["unrestricted double"] = (V, _prefix, _context, _opts) => {
return x;
};
converters.DOMString = function (V, prefix, context, opts = {}) {
converters.DOMString = function (
V,
prefix,
context,
opts = { __proto__: null },
) {
if (typeof V === "string") {
return V;
} else if (V === null && opts.treatNullAsEmptyString) {
@ -464,7 +479,7 @@ converters.ArrayBuffer = (
V,
prefix = undefined,
context = undefined,
opts = {},
opts = { __proto__: null },
) => {
if (!isArrayBuffer(V)) {
if (opts.allowShared && !isSharedArrayBuffer(V)) {
@ -490,7 +505,7 @@ converters.DataView = (
V,
prefix = undefined,
context = undefined,
opts = {},
opts = { __proto__: null },
) => {
if (!isDataView(V)) {
throw makeException(
@ -539,7 +554,7 @@ ArrayPrototypeForEach(
V,
prefix = undefined,
context = undefined,
opts = {},
opts = { __proto__: null },
) => {
if (TypedArrayPrototypeGetSymbolToStringTag(V) !== name) {
throw makeException(
@ -572,7 +587,7 @@ converters.ArrayBufferView = (
V,
prefix = undefined,
context = undefined,
opts = {},
opts = { __proto__: null },
) => {
if (!ArrayBufferIsView(V)) {
throw makeException(
@ -604,7 +619,7 @@ converters.BufferSource = (
V,
prefix = undefined,
context = undefined,
opts = {},
opts = { __proto__: null },
) => {
if (ArrayBufferIsView(V)) {
let buffer;
@ -722,7 +737,7 @@ function createDictionaryConverter(name, ...dictionaries) {
return a.key < b.key ? -1 : 1;
});
const defaultValues = {};
const defaultValues = { __proto__: null };
for (let i = 0; i < allMembers.length; ++i) {
const member = allMembers[i];
if (ReflectHas(member, "defaultValue")) {
@ -747,7 +762,12 @@ function createDictionaryConverter(name, ...dictionaries) {
}
}
return function (V, prefix = undefined, context = undefined, opts = {}) {
return function (
V,
prefix = undefined,
context = undefined,
opts = { __proto__: null },
) {
const typeV = type(V);
switch (typeV) {
case "Undefined":
@ -812,7 +832,12 @@ function createDictionaryConverter(name, ...dictionaries) {
function createEnumConverter(name, values) {
const E = new SafeSet(values);
return function (V, prefix = undefined, _context = undefined, _opts = {}) {
return function (
V,
prefix = undefined,
_context = undefined,
_opts = { __proto__: null },
) {
const S = String(V);
if (!E.has(S)) {
@ -828,7 +853,12 @@ function createEnumConverter(name, values) {
}
function createNullableConverter(converter) {
return (V, prefix = undefined, context = undefined, opts = {}) => {
return (
V,
prefix = undefined,
context = undefined,
opts = { __proto__: null },
) => {
// FIXME: If Type(V) is not Object, and the conversion to an IDL value is
// being performed due to V being assigned to an attribute whose type is a
// nullable callback function that is annotated with
@ -842,7 +872,12 @@ function createNullableConverter(converter) {
// https://heycam.github.io/webidl/#es-sequence
function createSequenceConverter(converter) {
return function (V, prefix = undefined, context = undefined, opts = {}) {
return function (
V,
prefix = undefined,
context = undefined,
opts = { __proto__: null },
) {
if (type(V) !== "Object") {
throw makeException(
TypeError,
@ -894,7 +929,7 @@ function createRecordConverter(keyConverter, valueConverter) {
context,
);
}
const result = {};
const result = { __proto__: null };
// Fast path for common case (not a Proxy)
if (!core.isProxy(V)) {
for (const key in V) {

View File

@ -474,7 +474,7 @@ class WebSocketError extends DOMException {
#closeCode;
#reason;
constructor(message = "", init = {}) {
constructor(message = "", init = { __proto__: null }) {
super(message, "WebSocketError");
this[webidl.brand] = webidl.brand;

View File

@ -268,7 +268,7 @@ const permissions = new Permissions(illegalConstructorKey);
/** Converts all file URLs in FS allowlists to paths. */
function serializePermissions(permissions) {
if (typeof permissions == "object" && permissions != null) {
const serializedPermissions = {};
const serializedPermissions = { __proto__: null };
for (
const key of new SafeArrayIterator(["read", "write", "run", "ffi"])
) {

View File

@ -91,7 +91,7 @@ class Worker extends EventTarget {
// still be messages left to receive.
#status = "RUNNING";
constructor(specifier, options = {}) {
constructor(specifier, options = { __proto__: null }) {
super();
specifier = String(specifier);
const {
@ -254,7 +254,7 @@ class Worker extends EventTarget {
}
};
postMessage(message, transferOrOptions = {}) {
postMessage(message, transferOrOptions = { __proto__: null }) {
const prefix = "Failed to execute 'postMessage' on 'MessagePort'";
webidl.requiredArguments(arguments.length, 1, prefix);
message = webidl.converters.any(message);

View File

@ -134,7 +134,7 @@ function run({
cmd,
cwd = undefined,
clearEnv = false,
env = {},
env = { __proto__: null },
gid = undefined,
uid = undefined,
stdout = "inherit",
@ -172,7 +172,7 @@ function spawnChildInner(opFn, command, apiName, {
args = [],
cwd = undefined,
clearEnv = false,
env = {},
env = { __proto__: null },
uid = undefined,
gid = undefined,
stdin = "null",
@ -181,7 +181,7 @@ function spawnChildInner(opFn, command, apiName, {
signal = undefined,
windowsRawArguments = false,
ipc = -1,
} = {}) {
} = { __proto__: null }) {
const child = opFn({
cmd: pathFromURL(command),
args: ArrayPrototypeMap(args, String),
@ -202,7 +202,7 @@ function spawnChildInner(opFn, command, apiName, {
});
}
function spawnChild(command, options = {}) {
function spawnChild(command, options = { __proto__: null }) {
return spawnChildInner(
op_spawn_child,
command,
@ -392,14 +392,14 @@ function spawnSync(command, {
args = [],
cwd = undefined,
clearEnv = false,
env = {},
env = { __proto__: null },
uid = undefined,
gid = undefined,
stdin = "null",
stdout = "piped",
stderr = "piped",
windowsRawArguments = false,
} = {}) {
} = { __proto__: null }) {
if (stdin === "piped") {
throw new TypeError(
"Piped stdin is not supported for this function, use 'Deno.Command().spawn()' instead",

View File

@ -26,7 +26,7 @@ function unbindSignal(rid) {
// Stores signal listeners and resource data. This has type of
// `Record<string, { rid: number | undefined, listeners: Set<() => void> }`
const signalData = {};
const signalData = { __proto__: null };
/** Gets the signal handlers and resource data of the given signal */
function getSignalData(signo) {

View File

@ -264,9 +264,9 @@ const unstableIds = {
workerOptions: 11,
};
const denoNsUnstableById = {};
const denoNsUnstableById = { __proto__: null };
// denoNsUnstableById[unstableIds.broadcastChannel] = {}
// denoNsUnstableById[unstableIds.broadcastChannel] = { __proto__: null }
denoNsUnstableById[unstableIds.cron] = {
cron: cron.cron,
@ -308,13 +308,13 @@ denoNsUnstableById[unstableIds.net] = {
),
};
// denoNsUnstableById[unstableIds.unsafeProto] = {}
// denoNsUnstableById[unstableIds.unsafeProto] = { __proto__: null }
denoNsUnstableById[unstableIds.webgpu] = {
UnsafeWindowSurface: webgpuSurface.UnsafeWindowSurface,
};
// denoNsUnstableById[unstableIds.workerOptions] = {}
// denoNsUnstableById[unstableIds.workerOptions] = { __proto__: null }
// when editing this list, also update unstableDenoProps in cli/tsc/99_main_compiler.js
const denoNsUnstable = {

View File

@ -145,7 +145,7 @@ const windowOrWorkerGlobalScope = {
[webidl.brand]: core.propNonEnumerable(webidl.brand),
};
const unstableForWindowOrWorkerGlobalScope = {};
const unstableForWindowOrWorkerGlobalScope = { __proto__: null };
unstableForWindowOrWorkerGlobalScope[unstableIds.broadcastChannel] = {
BroadcastChannel: core.propNonEnumerable(broadcastChannel.BroadcastChannel),
};

View File

@ -252,7 +252,7 @@ function workerClose() {
op_worker_close();
}
function postMessage(message, transferOrOptions = {}) {
function postMessage(message, transferOrOptions = { __proto__: null }) {
const prefix =
"Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope'";
webidl.requiredArguments(arguments.length, 1, prefix);

View File

@ -141,3 +141,17 @@ Deno.test(function inspectEvent() {
`Event {\n bubbles: false,\n cancelable: false,`,
);
});
Deno.test("default argument is null prototype", () => {
const event = new Event("test");
assertEquals(event.bubbles, false);
// @ts-ignore this is on purpose to check if overriding prototype
// has effect on `Event.
Object.prototype.bubbles = true;
const event2 = new Event("test");
assertEquals(event2.bubbles, false);
// @ts-ignore this is done on purpose
delete Object.prototype.bubbles;
});