From b2cd254c35b6b1b128beea0eacdb8e814d91e003 Mon Sep 17 00:00:00 2001 From: Kenta Moriuchi Date: Thu, 4 Jan 2024 13:12:38 +0900 Subject: fix: strict type check for cross realms (#21669) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deno v1.39 introduces `vm.runInNewContext`. This may cause problems when using `Object.prototype.isPrototypeOf` to check built-in types. ```js import vm from "node:vm"; const err = new Error(); const crossErr = vm.runInNewContext(`new Error()`); console.assert( !(crossErr instanceof Error) ); console.assert( Object.getPrototypeOf(err) !== Object.getPrototypeOf(crossErr) ); ``` This PR changes to check using internal slots solves them. --- current: ``` > import vm from "node:vm"; undefined > vm.runInNewContext(`new Error("message")`) Error {} > vm.runInNewContext(`new Date("2018-12-10T02:26:59.002Z")`) Date {} ``` this PR: ``` > import vm from "node:vm"; undefined > vm.runInNewContext(`new Error("message")`) Error: message at :1:1 > vm.runInNewContext(`new Date("2018-12-10T02:26:59.002Z")`) 2018-12-10T02:26:59.002Z ``` --------- Co-authored-by: Bartek IwaƄczuk --- ext/node/polyfills/internal/util/types.ts | 85 +++++++++++++------------------ 1 file changed, 34 insertions(+), 51 deletions(-) (limited to 'ext/node/polyfills/internal/util') diff --git a/ext/node/polyfills/internal/util/types.ts b/ext/node/polyfills/internal/util/types.ts index 3e2004c2b..58b1b1045 100644 --- a/ext/node/polyfills/internal/util/types.ts +++ b/ext/node/polyfills/internal/util/types.ts @@ -24,17 +24,16 @@ // TODO(petamoriken): enable prefer-primordials for node polyfills // deno-lint-ignore-file prefer-primordials +import { primordials } from "ext:core/mod.js"; import * as bindingTypes from "ext:deno_node/internal_binding/types.ts"; export { isCryptoKey, isKeyObject, } from "ext:deno_node/internal/crypto/_keys.ts"; - -// https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag -const _getTypedArrayToStringTag = Object.getOwnPropertyDescriptor( - Object.getPrototypeOf(Uint8Array).prototype, - Symbol.toStringTag, -)!.get!; +const { + ArrayBufferIsView, + TypedArrayPrototypeGetSymbolToStringTag, +} = primordials; export function isArrayBufferView( value: unknown, @@ -51,98 +50,82 @@ export function isArrayBufferView( | Uint8ClampedArray | Uint16Array | Uint32Array { - return ArrayBuffer.isView(value); + return ArrayBufferIsView(value); } export function isBigInt64Array(value: unknown): value is BigInt64Array { - return _getTypedArrayToStringTag.call(value) === "BigInt64Array"; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "BigInt64Array"; } export function isBigUint64Array(value: unknown): value is BigUint64Array { - return _getTypedArrayToStringTag.call(value) === "BigUint64Array"; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "BigUint64Array"; } export function isFloat32Array(value: unknown): value is Float32Array { - return _getTypedArrayToStringTag.call(value) === "Float32Array"; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "Float32Array"; } export function isFloat64Array(value: unknown): value is Float64Array { - return _getTypedArrayToStringTag.call(value) === "Float64Array"; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "Float64Array"; } export function isInt8Array(value: unknown): value is Int8Array { - return _getTypedArrayToStringTag.call(value) === "Int8Array"; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "Int8Array"; } export function isInt16Array(value: unknown): value is Int16Array { - return _getTypedArrayToStringTag.call(value) === "Int16Array"; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "Int16Array"; } export function isInt32Array(value: unknown): value is Int32Array { - return _getTypedArrayToStringTag.call(value) === "Int32Array"; -} - -export type TypedArray = - | BigInt64Array - | BigUint64Array - | Float32Array - | Float64Array - | Int8Array - | Int16Array - | Int32Array - | Uint8Array - | Uint8ClampedArray - | Uint16Array - | Uint32Array; - -export function isTypedArray(value: unknown): value is TypedArray { - return _getTypedArrayToStringTag.call(value) !== undefined; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "Int32Array"; } export function isUint8Array(value: unknown): value is Uint8Array { - return _getTypedArrayToStringTag.call(value) === "Uint8Array"; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "Uint8Array"; } export function isUint8ClampedArray( value: unknown, ): value is Uint8ClampedArray { - return _getTypedArrayToStringTag.call(value) === "Uint8ClampedArray"; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "Uint8ClampedArray"; } export function isUint16Array(value: unknown): value is Uint16Array { - return _getTypedArrayToStringTag.call(value) === "Uint16Array"; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "Uint16Array"; } export function isUint32Array(value: unknown): value is Uint32Array { - return _getTypedArrayToStringTag.call(value) === "Uint32Array"; + return TypedArrayPrototypeGetSymbolToStringTag(value) === "Uint32Array"; } export const { // isExternal, - isDate, + isAnyArrayBuffer, isArgumentsObject, + isArrayBuffer, + isAsyncFunction, isBigIntObject, isBooleanObject, - isNumberObject, - isStringObject, - isSymbolObject, - isNativeError, - isRegExp, - isAsyncFunction, + isBoxedPrimitive, + isDataView, + isDate, isGeneratorFunction, isGeneratorObject, - isPromise, isMap, - isSet, isMapIterator, + isModuleNamespaceObject, + isNativeError, + isNumberObject, + isPromise, + isProxy, + isRegExp, + isSet, isSetIterator, + isSharedArrayBuffer, + isStringObject, + isSymbolObject, + isTypedArray, isWeakMap, isWeakSet, - isArrayBuffer, - isDataView, - isSharedArrayBuffer, - isProxy, - isModuleNamespaceObject, - isAnyArrayBuffer, - isBoxedPrimitive, } = bindingTypes; -- cgit v1.2.3