diff options
author | Kenta Moriuchi <moriken@kimamass.com> | 2024-01-04 13:12:38 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-04 09:42:38 +0530 |
commit | b2cd254c35b6b1b128beea0eacdb8e814d91e003 (patch) | |
tree | d55fa5910e32d8a664aff5b680e07debea93181e /ext/node/polyfills/internal_binding | |
parent | 48556748577ba46db5f9212d14a0fcaa90d632f6 (diff) |
fix: strict type check for cross realms (#21669)
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 <anonymous>:1:1
> vm.runInNewContext(`new Date("2018-12-10T02:26:59.002Z")`)
2018-12-10T02:26:59.002Z
```
---------
Co-authored-by: Bartek IwaĆczuk <biwanczuk@gmail.com>
Diffstat (limited to 'ext/node/polyfills/internal_binding')
-rw-r--r-- | ext/node/polyfills/internal_binding/types.ts | 320 |
1 files changed, 18 insertions, 302 deletions
diff --git a/ext/node/polyfills/internal_binding/types.ts b/ext/node/polyfills/internal_binding/types.ts index aa3781944..2d301ba1b 100644 --- a/ext/node/polyfills/internal_binding/types.ts +++ b/ext/node/polyfills/internal_binding/types.ts @@ -21,319 +21,35 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -// TODO(petamoriken): enable prefer-primordials for node polyfills -// deno-lint-ignore-file prefer-primordials +import { core } from "ext:core/mod.js"; -const { core } = globalThis.__bootstrap; -const { ops } = core; - -// https://tc39.es/ecma262/#sec-bigint.prototype.valueof -const _bigIntValueOf = BigInt.prototype.valueOf; - -// https://tc39.es/ecma262/#sec-boolean.prototype.valueof -const _booleanValueOf = Boolean.prototype.valueOf; - -// https://tc39.es/ecma262/#sec-date.prototype.valueof -const _dateValueOf = Date.prototype.valueOf; - -// https://tc39.es/ecma262/#sec-number.prototype.valueof -const _numberValueOf = Number.prototype.valueOf; - -// https://tc39.es/ecma262/#sec-string.prototype.valueof -const _stringValueOf = String.prototype.valueOf; - -// https://tc39.es/ecma262/#sec-symbol.prototype.valueof -const _symbolValueOf = Symbol.prototype.valueOf; - -// https://tc39.es/ecma262/#sec-weakmap.prototype.has -const _weakMapHas = WeakMap.prototype.has; - -// https://tc39.es/ecma262/#sec-weakset.prototype.has -const _weakSetHas = WeakSet.prototype.has; - -// https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.bytelength -const _getArrayBufferByteLength = Object.getOwnPropertyDescriptor( - ArrayBuffer.prototype, - "byteLength", -)!.get!; - -// https://tc39.es/ecma262/#sec-get-sharedarraybuffer.prototype.bytelength -let _getSharedArrayBufferByteLength; - -// https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag -const _getTypedArrayToStringTag = Object.getOwnPropertyDescriptor( - Object.getPrototypeOf(Uint8Array).prototype, - Symbol.toStringTag, -)!.get!; - -// https://tc39.es/ecma262/#sec-get-set.prototype.size -const _getSetSize = Object.getOwnPropertyDescriptor( - Set.prototype, - "size", -)!.get!; - -// https://tc39.es/ecma262/#sec-get-map.prototype.size -const _getMapSize = Object.getOwnPropertyDescriptor( - Map.prototype, - "size", -)!.get!; - -function isObjectLike( - value: unknown, -): value is Record<string | number | symbol, unknown> { - return value !== null && typeof value === "object"; -} - -export function isAnyArrayBuffer( - value: unknown, -): value is ArrayBuffer | SharedArrayBuffer { - return ops.op_is_any_arraybuffer(value); -} - -export function isArgumentsObject(value: unknown): value is IArguments { - return core.isArgumentsObject(value); -} - -export function isArrayBuffer(value: unknown): value is ArrayBuffer { - try { - _getArrayBufferByteLength.call(value); - return true; - } catch { - return false; - } -} - -export function isAsyncFunction( - value: unknown, -): value is (...args: unknown[]) => Promise<unknown> { - return core.isAsyncFunction(value); -} - -// deno-lint-ignore ban-types -export function isBooleanObject(value: unknown): value is Boolean { - if (!isObjectLike(value)) { - return false; - } - - try { - _booleanValueOf.call(value); - return true; - } catch { - return false; - } -} - -export function isBoxedPrimitive( - value: unknown, - // deno-lint-ignore ban-types -): value is Boolean | String | Number | Symbol | BigInt { - return ( - isBooleanObject(value) || - isStringObject(value) || - isNumberObject(value) || - isSymbolObject(value) || - isBigIntObject(value) - ); -} - -export function isDataView(value: unknown): value is DataView { - return ( - ArrayBuffer.isView(value) && - _getTypedArrayToStringTag.call(value) === undefined - ); -} - -export function isDate(value: unknown): value is Date { - try { - _dateValueOf.call(value); - return true; - } catch { - return false; - } -} - -export function isGeneratorFunction( - value: unknown, -): value is GeneratorFunction { - return core.isGeneratorFunction(value); -} - -export function isGeneratorObject(value: unknown): value is Generator { - return core.isGeneratorObject(value); -} - -export function isMap(value: unknown): value is Map<unknown, unknown> { - try { - _getMapSize.call(value); - return true; - } catch { - return false; - } -} - -export function isMapIterator( - value: unknown, -): value is IterableIterator<[unknown, unknown]> { - return core.isMapIterator(value); -} - -export function isModuleNamespaceObject( - value: unknown, -): value is Record<string | number | symbol, unknown> { - return core.isModuleNamespaceObject(value); -} - -export function isNativeError(value: unknown): value is Error { - return core.isNativeError(value); -} - -// deno-lint-ignore ban-types -export function isNumberObject(value: unknown): value is Number { - if (!isObjectLike(value)) { - return false; - } - - try { - _numberValueOf.call(value); - return true; - } catch { - return false; - } -} - -export function isBigIntObject(value: unknown): value is bigint { - if (!isObjectLike(value)) { - return false; - } - - try { - _bigIntValueOf.call(value); - return true; - } catch { - return false; - } -} - -export function isPromise(value: unknown): value is Promise<unknown> { - return core.isPromise(value); -} - -export function isProxy( - value: unknown, -): value is Record<string | number | symbol, unknown> { - return core.isProxy(value); -} - -export function isRegExp(value: unknown): value is RegExp { - return core.isRegExp(value); -} - -export function isSet(value: unknown): value is Set<unknown> { - try { - _getSetSize.call(value); - return true; - } catch { - return false; - } -} - -export function isSetIterator( - value: unknown, -): value is IterableIterator<unknown> { - return core.isSetIterator(value); -} - -export function isSharedArrayBuffer( - value: unknown, -): value is SharedArrayBuffer { - // TODO(kt3k): add SharedArrayBuffer to primordials - _getSharedArrayBufferByteLength ??= Object.getOwnPropertyDescriptor( - SharedArrayBuffer.prototype, - "byteLength", - )!.get!; - - try { - _getSharedArrayBufferByteLength.call(value); - return true; - } catch { - return false; - } -} - -// deno-lint-ignore ban-types -export function isStringObject(value: unknown): value is String { - if (!isObjectLike(value)) { - return false; - } - - try { - _stringValueOf.call(value); - return true; - } catch { - return false; - } -} - -// deno-lint-ignore ban-types -export function isSymbolObject(value: unknown): value is Symbol { - if (!isObjectLike(value)) { - return false; - } - - try { - _symbolValueOf.call(value); - return true; - } catch { - return false; - } -} - -export function isWeakMap( - value: unknown, -): value is WeakMap<Record<string | number | symbol, unknown>, unknown> { - try { - // deno-lint-ignore no-explicit-any - _weakMapHas.call(value, null as any); - return true; - } catch { - return false; - } -} - -export function isWeakSet( - value: unknown, -): value is WeakSet<Record<string | number | symbol, unknown>> { - try { - // deno-lint-ignore no-explicit-any - _weakSetHas.call(value, null as any); - return true; - } catch { - return false; - } -} - -export default { - isAsyncFunction, - isGeneratorFunction, +export const { + // isExternal, isAnyArrayBuffer, - isArrayBuffer, isArgumentsObject, + isArrayBuffer, + isAsyncFunction, + isBigIntObject, + isBooleanObject, isBoxedPrimitive, isDataView, - // isExternal, + isDate, + isGeneratorFunction, + isGeneratorObject, isMap, isMapIterator, isModuleNamespaceObject, isNativeError, + isNumberObject, isPromise, + isProxy, + isRegExp, isSet, isSetIterator, + isSharedArrayBuffer, + isStringObject, + isSymbolObject, + isTypedArray, isWeakMap, isWeakSet, - isRegExp, - isDate, - isStringObject, - isNumberObject, - isBooleanObject, - isBigIntObject, -}; +} = core; |