diff --git a/.gitignore b/.gitignore index 3c3629e..22fbdbe 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ node_modules +yarn.lock +package-lock.json diff --git a/package.json b/package.json index ae59f69..551a229 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,15 @@ ], "scripts": { "test": "node test/node/index.js", - "test:browsers": "airtap test/browser/index.js" + "test:browsers": "airtap test/browser/index.js", + "test:browsers:local": "npm run test:browsers -- --local" }, "dependencies": { - "inherits": "2.0.3" + "inherits": "2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "object.entries": "^1.1.0", + "safe-buffer": "^5.1.2" }, "license": "MIT", "devDependencies": { diff --git a/support/types.js b/support/types.js new file mode 100644 index 0000000..2f6e701 --- /dev/null +++ b/support/types.js @@ -0,0 +1,419 @@ +// Currently in sync with Node.js lib/internal/util/types.js +// https://github.com/nodejs/node/commit/112cc7c27551254aa2b17098fb774867f05ed0d9 + +'use strict'; + +var isBuffer = require('./isBuffer'); + +var isArgumentsObject = require('is-arguments'); +var isGeneratorFunction = require('is-generator-function'); + +function uncurryThis(f) { + return f.call.bind(f); +} + +var BigIntSupported = typeof BigInt !== 'undefined'; +var SymbolSupported = typeof Symbol !== 'undefined'; +var SymbolToStringTagSupported = SymbolSupported && typeof Symbol.toStringTag !== 'undefined'; +var Uint8ArraySupported = typeof Uint8Array !== 'undefined'; +var ArrayBufferSupported = typeof ArrayBuffer !== 'undefined'; + +if (Uint8ArraySupported && SymbolToStringTagSupported) { + var TypedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype); + + var TypedArrayProto_toStringTag = + uncurryThis( + Object.getOwnPropertyDescriptor(TypedArrayPrototype, + Symbol.toStringTag).get); + +} + +var ObjectToString = uncurryThis(Object.prototype.toString); + +var numberValue = uncurryThis(Number.prototype.valueOf); +var stringValue = uncurryThis(String.prototype.valueOf); +var booleanValue = uncurryThis(Boolean.prototype.valueOf); + +if (BigIntSupported) { + var bigIntValue = uncurryThis(BigInt.prototype.valueOf); +} + +if (SymbolSupported) { + var symbolValue = uncurryThis(Symbol.prototype.valueOf); +} + +function checkBoxedPrimitive(value, prototypeValueOf) { + if (typeof value !== 'object') { + return false; + } + try { + prototypeValueOf(value); + return true; + } catch(e) { + return false; + } +} + +exports.isArgumentsObject = isArgumentsObject; + +exports.isGeneratorFunction = isGeneratorFunction; + +// Taken from here and modified for better browser support +// https://github.com/sindresorhus/p-is-promise/blob/cda35a513bda03f977ad5cde3a079d237e82d7ef/index.js +function isPromise(input) { + return ( + ( + typeof Promise !== 'undefined' && + input instanceof Promise + ) || + ( + input !== null && + typeof input === 'object' && + typeof input.then === 'function' && + typeof input.catch === 'function' + ) + ); +} +exports.isPromise = isPromise; + +function isArrayBufferView(value) { + if (ArrayBufferSupported && ArrayBuffer.isView) { + return ArrayBuffer.isView(value); + } + + return ( + isTypedArray(value) || + isDataView(value) + ); +} +exports.isArrayBufferView = isArrayBufferView; + +function isTypedArray(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) !== undefined; + } else { + return ( + isUint8Array(value) || + isUint8ClampedArray(value) || + isUint16Array(value) || + isUint32Array(value) || + isInt8Array(value) || + isInt16Array(value) || + isInt32Array(value) || + isFloat32Array(value) || + isFloat64Array(value) || + isBigInt64Array(value) || + isBigUint64Array(value) + ); + } +} +exports.isTypedArray = isTypedArray; + +function isUint8Array(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'Uint8Array'; + } else { + return ( + ObjectToString(value) === '[object Uint8Array]' || + isBuffer(value) + ); + } +} +exports.isUint8Array = isUint8Array; + +function isUint8ClampedArray(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'Uint8ClampedArray'; + } else { + return ObjectToString(value) === '[object Uint8ClampedArray]'; + } +} +exports.isUint8ClampedArray = isUint8ClampedArray; + +function isUint16Array(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'Uint16Array'; + } else { + return ObjectToString(value) === '[object Uint16Array]'; + } +} +exports.isUint16Array = isUint16Array; + +function isUint32Array(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'Uint32Array'; + } else { + return ObjectToString(value) === '[object Uint32Array]'; + } +} +exports.isUint32Array = isUint32Array; + +function isInt8Array(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'Int8Array'; + } else { + return ObjectToString(value) === '[object Int8Array]'; + } +} +exports.isInt8Array = isInt8Array; + +function isInt16Array(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'Int16Array'; + } else { + return ObjectToString(value) === '[object Int16Array]'; + } +} +exports.isInt16Array = isInt16Array; + +function isInt32Array(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'Int32Array'; + } else { + return ObjectToString(value) === '[object Int32Array]'; + } +} +exports.isInt32Array = isInt32Array; + +function isFloat32Array(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'Float32Array'; + } else { + return ObjectToString(value) === '[object Float32Array]'; + } +} +exports.isFloat32Array = isFloat32Array; + +function isFloat64Array(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'Float64Array'; + } else { + return ObjectToString(value) === '[object Float64Array]'; + } +} +exports.isFloat64Array = isFloat64Array; + +function isBigInt64Array(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'BigInt64Array'; + } else { + return ObjectToString(value) === '[object BigInt64Array]'; + } +} +exports.isBigInt64Array = isBigInt64Array; + +function isBigUint64Array(value) { + if (Uint8ArraySupported && SymbolToStringTagSupported) { + return TypedArrayProto_toStringTag(value) === 'BigUint64Array'; + } else { + return ObjectToString(value) === '[object BigUint64Array]'; + } +} +exports.isBigUint64Array = isBigUint64Array; + +function isMapToString(value) { + return ObjectToString(value) === '[object Map]'; +} +isMapToString.working = ( + typeof Map !== 'undefined' && + isMapToString(new Map()) +); + +function isMap(value) { + if (typeof Map === 'undefined') { + return false; + } + + return isMapToString.working + ? isMapToString(value) + : value instanceof Map; +} +exports.isMap = isMap; + +function isSetToString(value) { + return ObjectToString(value) === '[object Set]'; +} +isSetToString.working = ( + typeof Set !== 'undefined' && + isSetToString(new Set()) +); +function isSet(value) { + if (typeof Set === 'undefined') { + return false; + } + + return isSetToString.working + ? isSetToString(value) + : value instanceof Set; +} +exports.isSet = isSet; + +function isWeakMapToString(value) { + return ObjectToString(value) === '[object WeakMap]'; +} +isWeakMapToString.working = ( + typeof WeakMap !== 'undefined' && + isWeakMapToString(new WeakMap()) +); +function isWeakMap(value) { + if (typeof WeakMap === 'undefined') { + return false; + } + + return isWeakMapToString.working + ? isWeakMapToString(value) + : value instanceof WeakMap; +} +exports.isWeakMap = isWeakMap; + +function isWeakSetToString(value) { + return ObjectToString(value) === '[object WeakSet]'; +} +isWeakSetToString.working = ( + typeof WeakSet !== 'undefined' && + isWeakSetToString(new WeakSet()) +); +function isWeakSet(value) { + return isWeakSetToString(value); + if (typeof WeakSet === 'undefined') { + return false; + } + + return isWeakSetToString.working + ? isWeakSetToString(value) + : value instanceof WeakSet; +} +exports.isWeakSet = isWeakSet; + +function isArrayBufferToString(value) { + return ObjectToString(value) === '[object ArrayBuffer]'; +} +isArrayBufferToString.working = ( + typeof ArrayBuffer !== 'undefined' && + isArrayBufferToString(new ArrayBuffer()) +); +function isArrayBuffer(value) { + if (typeof ArrayBuffer === 'undefined') { + return false; + } + + return isArrayBufferToString.working + ? isArrayBufferToString(value) + : value instanceof ArrayBuffer; +} +exports.isArrayBuffer = isArrayBuffer; + +function isDataViewToString(value) { + return ObjectToString(value) === '[object DataView]'; +} +isDataViewToString.working = ( + typeof ArrayBuffer !== 'undefined' && + typeof DataView !== 'undefined' && + isDataViewToString(new DataView(new ArrayBuffer())) +); +function isDataView(value) { + if (typeof DataView === 'undefined') { + return false; + } + + return isDataViewToString.working + ? isDataViewToString(value) + : value instanceof DataView; +} +exports.isDataView = isDataView; + +function isSharedArrayBufferToString(value) { + return ObjectToString(value) === '[object SharedArrayBuffer]'; +} +isSharedArrayBufferToString.working = ( + typeof SharedArrayBuffer !== 'undefined' && + isSharedArrayBufferToString(new SharedArrayBuffer()) +); +function isSharedArrayBuffer(value) { + if (typeof SharedArrayBuffer === 'undefined') { + return false; + } + + return isSharedArrayBufferToString.working + ? isSharedArrayBufferToString(value) + : value instanceof SharedArrayBuffer; +} +exports.isSharedArrayBuffer = isSharedArrayBuffer; + +function isAsyncFunction(value) { + return ObjectToString(value) === '[object AsyncFunction]'; +} +exports.isAsyncFunction = isAsyncFunction; + +function isMapIterator(value) { + return ObjectToString(value) === '[object Map Iterator]'; +} +exports.isMapIterator = isMapIterator; + +function isSetIterator(value) { + return ObjectToString(value) === '[object Set Iterator]'; +} +exports.isSetIterator = isSetIterator; + +function isGeneratorObject(value) { + return ObjectToString(value) === '[object Generator]'; +} +exports.isGeneratorObject = isGeneratorObject; + +function isWebAssemblyCompiledModule(value) { + return ObjectToString(value) === '[object WebAssembly.Module]'; +} +exports.isWebAssemblyCompiledModule = isWebAssemblyCompiledModule; + +function isNumberObject(value) { + return checkBoxedPrimitive(value, numberValue); +} +exports.isNumberObject = isNumberObject; + +function isStringObject(value) { + return checkBoxedPrimitive(value, stringValue); +} +exports.isStringObject = isStringObject; + +function isBooleanObject(value) { + return checkBoxedPrimitive(value, booleanValue); +} +exports.isBooleanObject = isBooleanObject; + +function isBigIntObject(value) { + return BigIntSupported && checkBoxedPrimitive(value, bigIntValue); +} +exports.isBigIntObject = isBigIntObject; + +function isSymbolObject(value) { + return SymbolSupported && checkBoxedPrimitive(value, symbolValue); +} +exports.isSymbolObject = isSymbolObject; + +function isBoxedPrimitive(value) { + return ( + isNumberObject(value) || + isStringObject(value) || + isBooleanObject(value) || + isBigIntObject(value) || + isSymbolObject(value) + ); +} +exports.isBoxedPrimitive = isBoxedPrimitive; + +function isAnyArrayBuffer(value) { + return Uint8ArraySupported && ( + isArrayBuffer(value) || + isSharedArrayBuffer(value) + ); +} +exports.isAnyArrayBuffer = isAnyArrayBuffer; + +['isProxy', 'isExternal', 'isModuleNamespaceObject'].forEach(function(method) { + Object.defineProperty(exports, method, { + enumerable: false, + value: function() { + throw new Error(method + ' is not supported in userland'); + } + }); +}); diff --git a/test/browser/index.js b/test/browser/index.js index 28b2e5a..5ada4ba 100644 --- a/test/browser/index.js +++ b/test/browser/index.js @@ -2,3 +2,4 @@ require('./inspect'); require('./is'); require('./promisify'); require('./callbackify'); +require('./types'); diff --git a/test/browser/types.js b/test/browser/types.js new file mode 100644 index 0000000..ed8003b --- /dev/null +++ b/test/browser/types.js @@ -0,0 +1,7 @@ +var test = require('tape'); +var util = require('../../'); + +test('util.types', function (t) { + t.doesNotThrow(function () { return require('../node/types') }); + t.end(); +}); diff --git a/test/node/index.js b/test/node/index.js index a3a807f..64b5678 100644 --- a/test/node/index.js +++ b/test/node/index.js @@ -17,5 +17,8 @@ series([ test(require.resolve('./inspect')), test(require.resolve('./log')), test(require.resolve('./promisify')), - test(require.resolve('./callbackify')) -]); + test(require.resolve('./callbackify')), + test(require.resolve('./types')) +], function (err) { + if (err) throw err +}); diff --git a/test/node/types.js b/test/node/types.js new file mode 100644 index 0000000..e8fbbe2 --- /dev/null +++ b/test/node/types.js @@ -0,0 +1,511 @@ +// Currently in sync with Node.js test/parallel/test-util-types.js +// https://github.com/nodejs/node/commit/519a11b24fa453e5cefe13df10ab9696616b5b91 + +// Flags: --experimental-vm-modules --expose-internals +'use strict'; + +function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } +function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } +function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +require('./common'); +var assert = require('assert'); +var _require = require('../../'), + types = _require.types; +var vm = require('vm'); + +var Buffer = require('safe-buffer').Buffer +var objectEntries = require('object.entries'); + +function uncurryThis(f) { + return f.call.bind(f); +} + +var ObjectToString = uncurryThis(Object.prototype.toString); + +var inspect = function inspect(value) { + try { + return JSON.stringify(value); + } catch (e) { + return ObjectToString(value); + } +}; + +// [browserify] We can't test this in userland +// const { internalBinding } = require('internal/test/binding'); +// const { JSStream } = internalBinding('js_stream'); +// const external = (new JSStream())._externalStream; + +var wasmBuffer = Buffer.from('0061736d01000000', 'hex'); + +for (var _i = 0, _arr = [ + // [ external, 'isExternal' ], + [function () { return new Date(); }, 'isDate'], + [function () { return function () { return arguments; }(); }, 'isArgumentsObject'], + [function () { return new Boolean(); }, 'isBooleanObject'], + [function () { return new Number(); }, 'isNumberObject'], + [function () { return new String(); }, 'isStringObject'], + [function () { return Object(Symbol()); }, 'isSymbolObject'], + [function () { return Object(BigInt(0)); }, 'isBigIntObject'], + [function () { return new Error(); }, 'isNativeError'], + [function () { return new RegExp(); }, 'isRegExp'], + [function () { return eval('(async function() {})'); }, 'isAsyncFunction'], + [function () { return eval('(function*() {})') }, 'isGeneratorFunction'], + [function () { return eval('((function*() {})())') }, 'isGeneratorObject'], + [function () { return Promise.resolve(); }, 'isPromise'], + [function () { return new Map(); }, 'isMap'], + [function () { return new Set(); }, 'isSet'], + [function () { return new Map()[Symbol.iterator](); }, 'isMapIterator'], + [function () { return new Set()[Symbol.iterator](); }, 'isSetIterator'], + [function () { return new WeakMap(); }, 'isWeakMap'], + [function () { return new WeakSet(); }, 'isWeakSet'], + [function () { return new ArrayBuffer(1); }, 'isArrayBuffer'], + [function () { return new Uint8Array(); }, 'isUint8Array'], + [function () { return new Uint8ClampedArray(); }, 'isUint8ClampedArray'], + [function () { return new Uint16Array(); }, 'isUint16Array'], + [function () { return new Uint32Array(); }, 'isUint32Array'], + [function () { return new Int8Array(); }, 'isInt8Array'], + [function () { return new Int16Array(); }, 'isInt16Array'], + [function () { return new Int32Array(); }, 'isInt32Array'], + [function () { return new Float32Array(); }, 'isFloat32Array'], + [function () { return new Float64Array(); }, 'isFloat64Array'], + [function () { return new BigInt64Array(); }, 'isBigInt64Array'], + [function () { return new BigUint64Array(); }, 'isBigUint64Array'], + [function () { + if (typeof Symbol === 'undefined' || typeof Symbol.toStringTag === 'undefined') { + throw Error(); + } + + return Object.defineProperty(new Uint8Array(), Symbol.toStringTag, { + value: 'foo' + }); + }, 'isUint8Array'], + [function () { return new DataView(new ArrayBuffer(1)); }, 'isDataView'], + [function () { return new SharedArrayBuffer(); }, 'isSharedArrayBuffer'], + // [ new Proxy({}, {}), 'isProxy' ], + [function () { return new WebAssembly.Module(wasmBuffer); }, 'isWebAssemblyCompiledModule'] +]; _i < _arr.length; _i++) { + var _arr$_i = _slicedToArray(_arr[_i], 2), + getValue = _arr$_i[0], + method = _arr$_i[1]; + + var _value = void 0; + try { + _value = getValue(); + } catch (e) { + console.log('Skipping unsupported type:', getValue); + continue; + } + console.log('Testing', method); + assert(method in types, "Missing ".concat(method, " for ").concat(inspect(_value))); + assert(types[method](_value), "Want ".concat(inspect(_value), " to match ").concat(method)); + + for (var _i3 = 0, _Object$keys2 = Object.keys(types); _i3 < _Object$keys2.length; _i3++) { + var key = _Object$keys2[_i3]; + if ((types.isArrayBufferView(_value) || + types.isAnyArrayBuffer(_value)) && key.indexOf('Array') > -1 || + key === 'isBoxedPrimitive') { + continue; + } + + assert.strictEqual(types[key](_value), + key === method, + "".concat(inspect(_value), ": ").concat(key, ", ") + + "".concat(method, ", ").concat(types[key](_value))); + } +} + +// Check boxed primitives. +console.log('Testing', 'isBoxedPrimitive'); +[ + function () { return new Boolean(); }, + function () { return new Number(); }, + function () { return new String(); }, + function () { return Object(Symbol()); }, + function () { return Object(BigInt(0)); } +].forEach(function (getEntry) { + var entry; + try { + entry = getEntry(); + } catch (e) { + return; + } + assert(types.isBoxedPrimitive(entry)); +}); + +var SymbolSupported = typeof Symbol !== 'undefined'; +var SymbolToStringTagSupported = SymbolSupported && typeof Symbol.toStringTag !== 'undefined'; +if (SymbolToStringTagSupported) { + [ + 'Uint8Array', + 'Uint8ClampedArray', + 'Uint16Array', + 'Uint32Array', + 'Int8Array', + 'Int16Array', + 'Int32Array', + 'Float32Array', + 'Float64Array', + 'BigInt64Array', + 'BigUint64Array' + ].forEach(function (typedArray) { + var method = 'is' + typedArray; + var constructor = 'new ' + typedArray; + var array; + try { + array = vm.runInNewContext(constructor); + } catch (e) { + return; + } + console.log('Testing fake typed arrays', method); + assert(!types[method](_defineProperty({}, Symbol.toStringTag, typedArray))); + assert(types[method](array)); + }); +} + +{ + var primitive = function primitive() { return true; }; + var arrayBuffer = function arrayBuffer() { return new ArrayBuffer(1); }; + + var buffer = function buffer() { return Buffer.from(arrayBuffer()); }; + var dataView = function dataView() { return new DataView(arrayBuffer()); }; + var uint8Array = function uint8Array() { return new Uint8Array(arrayBuffer()); }; + var uint8ClampedArray = function uint8ClampedArray() { return new Uint8ClampedArray(arrayBuffer()); }; + var uint16Array = function uint16Array() { return new Uint16Array(arrayBuffer()); }; + var uint32Array = function uint32Array() { return new Uint32Array(arrayBuffer()); }; + var int8Array = function int8Array() { return new Int8Array(arrayBuffer()); }; + var int16Array = function int16Array() { return new Int16Array(arrayBuffer()); }; + var int32Array = function int32Array() { return new Int32Array(arrayBuffer()); }; + var float32Array = function float32Array() { return new Float32Array(arrayBuffer()); }; + var float64Array = function float64Array() { return new Float64Array(arrayBuffer()); }; + var bigInt64Array = function bigInt64Array() { return new BigInt64Array(arrayBuffer()); }; + var bigUint64Array = function bigUint64Array() { return new BigUint64Array(arrayBuffer()); }; + + var fakeBuffer = function fakeBuffer() { + if (!SymbolToStringTagSupported) { + throw new Error(); + } + return Object.create(Buffer.prototype); + }; + var fakeDataView = function fakeDataView() { + if (!SymbolToStringTagSupported) { + throw new Error(); + } + return Object.create(DataView.prototype); + }; + var fakeUint8Array = function fakeUint8Array() { return Object.create(Uint8Array.prototype); }; + var fakeUint8ClampedArray = function fakeUint8ClampedArray() { return Object.create(Uint8ClampedArray.prototype); }; + var fakeUint16Array = function fakeUint16Array() { return Object.create(Uint16Array.prototype); }; + var fakeUint32Array = function fakeUint32Array() { return Object.create(Uint32Array.prototype); }; + var fakeInt8Array = function fakeInt8Array() { return Object.create(Int8Array.prototype); }; + var fakeInt16Array = function fakeInt16Array() { return Object.create(Int16Array.prototype); }; + var fakeInt32Array = function fakeInt32Array() { return Object.create(Int32Array.prototype); }; + var fakeFloat32Array = function fakeFloat32Array() { return Object.create(Float32Array.prototype); }; + var fakeFloat64Array = function fakeFloat64Array() { return Object.create(Float64Array.prototype); }; + var fakeBigInt64Array = function fakeBigInt64Array() { return Object.create(BigInt64Array.prototype); }; + var fakeBigUint64Array = function fakeBigUint64Array() { return Object.create(BigUint64Array.prototype); }; + + var stealthyDataView = function stealthyDataView() { + return Object.setPrototypeOf(new DataView(arrayBuffer()), Uint8Array.prototype); + }; + var stealthyUint8Array = function stealthyUint8Array() { + return Object.setPrototypeOf(new Uint8Array(arrayBuffer()), ArrayBuffer.prototype); + }; + var stealthyUint8ClampedArray = function stealthyUint8ClampedArray() { + return Object.setPrototypeOf(new Uint8ClampedArray(arrayBuffer()), ArrayBuffer.prototype); + }; + var stealthyUint16Array = function stealthyUint16Array() { + return Object.setPrototypeOf(new Uint16Array(arrayBuffer()), Uint16Array.prototype); + }; + var stealthyUint32Array = function stealthyUint32Array() { + return Object.setPrototypeOf(new Uint32Array(arrayBuffer()), Uint32Array.prototype); + }; + var stealthyInt8Array = function stealthyInt8Array() { + return Object.setPrototypeOf(new Int8Array(arrayBuffer()), Int8Array.prototype); + }; + var stealthyInt16Array = function stealthyInt16Array() { + return Object.setPrototypeOf(new Int16Array(arrayBuffer()), Int16Array.prototype); + }; + var stealthyInt32Array = function stealthyInt32Array() { + return Object.setPrototypeOf(new Int32Array(arrayBuffer()), Int32Array.prototype); + }; + var stealthyFloat32Array = function stealthyFloat32Array() { + return Object.setPrototypeOf(new Float32Array(arrayBuffer()), Float32Array.prototype); + }; + var stealthyFloat64Array = function stealthyFloat64Array() { + return Object.setPrototypeOf(new Float64Array(arrayBuffer()), Float64Array.prototype); + }; + var stealthyBigInt64Array = function stealthyBigInt64Array() { + return Object.setPrototypeOf(new BigInt64Array(arrayBuffer()), BigInt64Array.prototype); + }; + var stealthyBigUint64Array = function stealthyBigUint64Array() { + return Object.setPrototypeOf(new BigUint64Array(arrayBuffer()), BigUint64Array.prototype); + }; + + var typedArrays = objectEntries({ + primitive: primitive, + arrayBuffer: arrayBuffer, + buffer: buffer, + fakeBuffer: fakeBuffer, + dataView: dataView, + fakeDataView: fakeDataView, + stealthyDataView: stealthyDataView, + uint8Array: uint8Array, + fakeUint8Array: fakeUint8Array, + stealthyUint8Array: stealthyUint8Array, + uint8ClampedArray: uint8ClampedArray, + fakeUint8ClampedArray: fakeUint8ClampedArray, + stealthyUint8ClampedArray: stealthyUint8ClampedArray, + uint16Array: uint16Array, + fakeUint16Array: fakeUint16Array, + stealthyUint16Array: stealthyUint16Array, + uint32Array: uint32Array, + fakeUint32Array: fakeUint32Array, + stealthyUint32Array: stealthyUint32Array, + int8Array: int8Array, + fakeInt8Array: fakeInt8Array, + stealthyInt8Array: stealthyInt8Array, + int16Array: int16Array, + fakeInt16Array: fakeInt16Array, + stealthyInt16Array: stealthyInt16Array, + int32Array: int32Array, + fakeInt32Array: fakeInt32Array, + stealthyInt32Array: stealthyInt32Array, + float32Array: float32Array, + fakeFloat32Array: fakeFloat32Array, + stealthyFloat32Array: stealthyFloat32Array, + float64Array: float64Array, + fakeFloat64Array: fakeFloat64Array, + stealthyFloat64Array: stealthyFloat64Array, + bigInt64Array: bigInt64Array, + fakeBigInt64Array: fakeBigInt64Array, + stealthyBigInt64Array: stealthyBigInt64Array, + bigUint64Array: bigUint64Array, + fakeBigUint64Array: fakeBigUint64Array, + stealthyBigUint64Array: stealthyBigUint64Array + }); + typedArrays.forEach(function (_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + createTypedArray = _ref2[1]; + + try { + typedArrays[key] = createTypedArray(); + } catch (e) { + typedArrays[key] = undefined; + } + }); + + primitive = typedArrays.primitive; + arrayBuffer = typedArrays.arrayBuffer; + buffer = typedArrays.buffer; + fakeBuffer = typedArrays.fakeBuffer; + dataView = typedArrays.dataView; + fakeDataView = typedArrays.fakeDataView; + stealthyDataView = typedArrays.stealthyDataView; + uint8Array = typedArrays.uint8Array; + fakeUint8Array = typedArrays.fakeUint8Array; + stealthyUint8Array = typedArrays.stealthyUint8Array; + uint8ClampedArray = typedArrays.uint8ClampedArray; + fakeUint8ClampedArray = typedArrays.fakeUint8ClampedArray; + stealthyUint8ClampedArray = typedArrays.stealthyUint8ClampedArray; + uint16Array = typedArrays.uint16Array; + fakeUint16Array = typedArrays.fakeUint16Array; + stealthyUint16Array = typedArrays.stealthyUint16Array; + uint32Array = typedArrays.uint32Array; + fakeUint32Array = typedArrays.fakeUint32Array; + stealthyUint32Array = typedArrays.stealthyUint32Array; + int8Array = typedArrays.int8Array; + fakeInt8Array = typedArrays.fakeInt8Array; + stealthyInt8Array = typedArrays.stealthyInt8Array; + int16Array = typedArrays.int16Array; + fakeInt16Array = typedArrays.fakeInt16Array; + stealthyInt16Array = typedArrays.stealthyInt16Array; + int32Array = typedArrays.int32Array; + fakeInt32Array = typedArrays.fakeInt32Array; + stealthyInt32Array = typedArrays.stealthyInt32Array; + float32Array = typedArrays.float32Array; + fakeFloat32Array = typedArrays.fakeFloat32Array; + stealthyFloat32Array = typedArrays.stealthyFloat32Array; + float64Array = typedArrays.float64Array; + fakeFloat64Array = typedArrays.fakeFloat64Array; + stealthyFloat64Array = typedArrays.stealthyFloat64Array; + bigInt64Array = typedArrays.bigInt64Array; + fakeBigInt64Array = typedArrays.fakeBigInt64Array; + stealthyBigInt64Array = typedArrays.stealthyBigInt64Array; + bigUint64Array = typedArrays.bigUint64Array; + fakeBigUint64Array = typedArrays.fakeBigUint64Array; + stealthyBigUint64Array = typedArrays.stealthyBigUint64Array; + + var all = [ + primitive, + arrayBuffer, + buffer, + fakeBuffer, + dataView, + fakeDataView, + stealthyDataView, + uint8Array, + fakeUint8Array, + stealthyUint8Array, + uint8ClampedArray, + fakeUint8ClampedArray, + stealthyUint8ClampedArray, + uint16Array, + fakeUint16Array, + stealthyUint16Array, + uint32Array, + fakeUint32Array, + stealthyUint32Array, + int8Array, + fakeInt8Array, + stealthyInt8Array, + int16Array, + fakeInt16Array, + stealthyInt16Array, + int32Array, + fakeInt32Array, + stealthyInt32Array, + float32Array, + fakeFloat32Array, + stealthyFloat32Array, + float64Array, + fakeFloat64Array, + stealthyFloat64Array, + bigInt64Array, + fakeBigInt64Array, + stealthyBigInt64Array, + bigUint64Array, + fakeBigUint64Array, + stealthyBigUint64Array + ]; + + var expected = { + isArrayBufferView: [ + buffer, + dataView, + stealthyDataView, + uint8Array, + stealthyUint8Array, + uint8ClampedArray, + stealthyUint8ClampedArray, + uint16Array, + stealthyUint16Array, + uint32Array, + stealthyUint32Array, + int8Array, + stealthyInt8Array, + int16Array, + stealthyInt16Array, + int32Array, + stealthyInt32Array, + float32Array, + stealthyFloat32Array, + float64Array, + stealthyFloat64Array, + bigInt64Array, + stealthyBigInt64Array, + bigUint64Array, + stealthyBigUint64Array + ], + isTypedArray: [ + buffer, + uint8Array, + stealthyUint8Array, + uint8ClampedArray, + stealthyUint8ClampedArray, + uint16Array, + stealthyUint16Array, + uint32Array, + stealthyUint32Array, + int8Array, + stealthyInt8Array, + int16Array, + stealthyInt16Array, + int32Array, + stealthyInt32Array, + float32Array, + stealthyFloat32Array, + float64Array, + stealthyFloat64Array, + bigInt64Array, + stealthyBigInt64Array, + bigUint64Array, + stealthyBigUint64Array + ], + isUint8Array: [ + buffer, + uint8Array, + stealthyUint8Array + ], + isUint8ClampedArray: [ + uint8ClampedArray, + stealthyUint8ClampedArray + ], + isUint16Array: [ + uint16Array, + stealthyUint16Array + ], + isUint32Array: [ + uint32Array, + stealthyUint32Array + ], + isInt8Array: [ + int8Array, + stealthyInt8Array + ], + isInt16Array: [ + int16Array, + stealthyInt16Array + ], + isInt32Array: [ + int32Array, + stealthyInt32Array + ], + isFloat32Array: [ + float32Array, + stealthyFloat32Array + ], + isFloat64Array: [ + float64Array, + stealthyFloat64Array + ], + isBigInt64Array: [ + bigInt64Array, + stealthyBigInt64Array + ], + isBigUint64Array: [ + bigUint64Array, + stealthyBigUint64Array + ] + }; + + Object.keys(expected).forEach(function (testedFunc) { + console.log('Testing values for:', testedFunc); + var func = types[testedFunc]; + var yup = []; + + all + .filter(function (a) { return typeof a !== 'undefined'; }) + .forEach(function (value) { + if (func(value)) { + yup.push(value); + } + }); + + assert.deepStrictEqual( + yup, + expected[testedFunc].filter(function (a) { return typeof a !== 'undefined'; }) + ); + }); +} + +// (async () => { +// const m = new vm.SourceTextModule(''); +// await m.link(() => 0); +// m.instantiate(); +// await m.evaluate(); +// assert.ok(types.isModuleNamespaceObject(m.namespace)); +// })(); diff --git a/util.js b/util.js index 4f25671..f717622 100644 --- a/util.js +++ b/util.js @@ -457,6 +457,8 @@ function reduceToSingleString(output, base, braces) { // NOTE: These type checking functions intentionally don't use `instanceof` // because it is fragile and can be easily faked with `Object.create()`. +exports.types = require('./support/types'); + function isArray(ar) { return Array.isArray(ar); } @@ -501,6 +503,7 @@ function isRegExp(re) { return isObject(re) && objectToString(re) === '[object RegExp]'; } exports.isRegExp = isRegExp; +exports.types.isRegExp = isRegExp; function isObject(arg) { return typeof arg === 'object' && arg !== null; @@ -511,12 +514,14 @@ function isDate(d) { return isObject(d) && objectToString(d) === '[object Date]'; } exports.isDate = isDate; +exports.types.isDate = isDate; function isError(e) { return isObject(e) && (objectToString(e) === '[object Error]' || e instanceof Error); } exports.isError = isError; +exports.types.isNativeError = isError; function isFunction(arg) { return typeof arg === 'function';