diff options
author | Anna Henningsen <anna@addaleax.net> | 2018-01-27 22:01:32 +0100 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2018-03-05 17:41:26 +0000 |
commit | b20af8088a4d5cccb1901d42107f6d9ca82d306f (patch) | |
tree | d443fa727be877dc7ad6e4112503944a8e674490 /test/parallel/test-util-types.js | |
parent | bd6e0be0dfbbf6d10f1f054c43b0b82f25c60b16 (diff) | |
download | android-node-v8-b20af8088a4d5cccb1901d42107f6d9ca82d306f.tar.gz android-node-v8-b20af8088a4d5cccb1901d42107f6d9ca82d306f.tar.bz2 android-node-v8-b20af8088a4d5cccb1901d42107f6d9ca82d306f.zip |
util: introduce `util.types.is[…]` type checks
Provide public APIs for native typechecking that is actually useful.
The motivation for this is providing alternatives to userland
modules that would currently rely on `process.binding('util')`.
PR-URL: https://github.com/nodejs/node/pull/18415
Reviewed-By: Evan Lucas <evanlucas@me.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Сковорода Никита Андреевич <chalkerx@gmail.com>
Diffstat (limited to 'test/parallel/test-util-types.js')
-rw-r--r-- | test/parallel/test-util-types.js | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/test/parallel/test-util-types.js b/test/parallel/test-util-types.js new file mode 100644 index 0000000000..f9211ddf42 --- /dev/null +++ b/test/parallel/test-util-types.js @@ -0,0 +1,162 @@ +/*global SharedArrayBuffer*/ +'use strict'; +const common = require('../common'); +const fixtures = require('../common/fixtures'); +const assert = require('assert'); +const { types, inspect } = require('util'); +const path = require('path'); +const fs = require('fs'); +const vm = require('vm'); +const { JSStream } = process.binding('js_stream'); + +common.crashOnUnhandledRejection(); + +const external = (new JSStream())._externalStream; +const wasmBuffer = fixtures.readSync('test.wasm'); + +for (const [ value, _method ] of [ + [ external, 'isExternal' ], + [ new Date() ], + [ (function() { return arguments; })(), 'isArgumentsObject' ], + [ new Boolean(), 'isBooleanObject' ], + [ new Number(), 'isNumberObject' ], + [ new String(), 'isStringObject' ], + [ Object(Symbol()), 'isSymbolObject' ], + [ new Error(), 'isNativeError' ], + [ new RegExp() ], + [ async function() {}, 'isAsyncFunction' ], + [ function*() {}, 'isGeneratorFunction' ], + [ (function*() {})(), 'isGeneratorObject' ], + [ Promise.resolve() ], + [ new Map() ], + [ new Set() ], + [ (new Map())[Symbol.iterator](), 'isMapIterator' ], + [ (new Set())[Symbol.iterator](), 'isSetIterator' ], + [ new WeakMap() ], + [ new WeakSet() ], + [ new ArrayBuffer() ], + [ new Uint8Array() ], + [ new Uint8ClampedArray() ], + [ new Uint16Array() ], + [ new Uint32Array() ], + [ new Int8Array() ], + [ new Int16Array() ], + [ new Int32Array() ], + [ new Float32Array() ], + [ new Float64Array() ], + [ Object.defineProperty(new Uint8Array(), + Symbol.toStringTag, + { value: 'foo' }) ], + [ new DataView(new ArrayBuffer()) ], + [ new SharedArrayBuffer() ], + [ new Proxy({}, {}), 'isProxy' ], + [ new WebAssembly.Module(wasmBuffer), 'isWebAssemblyCompiledModule' ], +]) { + const method = _method || `is${value.constructor.name}`; + assert(method in types, `Missing ${method} for ${inspect(value)}`); + assert(types[method](value), `Want ${inspect(value)} to match ${method}`); + + for (const key of Object.keys(types)) { + if ((types.isArrayBufferView(value) || + types.isAnyArrayBuffer(value)) && key.includes('Array')) { + continue; + } + + assert.strictEqual(types[key](value), + key === method, + `${inspect(value)}: ${key}, ` + + `${method}, ${types[key](value)}`); + } +} + +{ + assert(!types.isUint8Array({ [Symbol.toStringTag]: 'Uint8Array' })); + assert(types.isUint8Array(vm.runInNewContext('new Uint8Array'))); +} + +{ + const primitive = true; + const arrayBuffer = new ArrayBuffer(); + const dataView = new DataView(arrayBuffer); + const int32Array = new Int32Array(arrayBuffer); + const uint8Array = new Uint8Array(arrayBuffer); + const buffer = Buffer.from(arrayBuffer); + + const fakeDataView = Object.create(DataView.prototype); + const fakeInt32Array = Object.create(Int32Array.prototype); + const fakeUint8Array = Object.create(Uint8Array.prototype); + const fakeBuffer = Object.create(Buffer.prototype); + + const stealthyDataView = + Object.setPrototypeOf(new DataView(arrayBuffer), Uint8Array.prototype); + const stealthyInt32Array = + Object.setPrototypeOf(new Int32Array(arrayBuffer), uint8Array); + const stealthyUint8Array = + Object.setPrototypeOf(new Uint8Array(arrayBuffer), ArrayBuffer.prototype); + + const all = [ + primitive, arrayBuffer, dataView, int32Array, uint8Array, buffer, + fakeDataView, fakeInt32Array, fakeUint8Array, fakeBuffer, + stealthyDataView, stealthyInt32Array, stealthyUint8Array + ]; + + const expected = { + isArrayBufferView: [ + dataView, int32Array, uint8Array, buffer, + stealthyDataView, stealthyInt32Array, stealthyUint8Array + ], + isTypedArray: [ + int32Array, uint8Array, buffer, stealthyInt32Array, stealthyUint8Array + ], + isUint8Array: [ + uint8Array, buffer, stealthyUint8Array + ] + }; + + for (const testedFunc of Object.keys(expected)) { + const func = types[testedFunc]; + const yup = []; + for (const value of all) { + if (func(value)) { + yup.push(value); + } + } + console.log('Testing', testedFunc); + assert.deepStrictEqual(yup, expected[testedFunc]); + } +} + + +// Try reading the v8.h header to verify completeness. + +let v8_h; +try { + v8_h = fs.readFileSync(path.resolve( + __dirname, '..', '..', 'deps', 'v8', 'include', 'v8.h'), 'utf8'); +} catch (e) { + // If loading the header fails, it should fail because we did not find it. + assert.strictEqual(e.code, 'ENOENT'); + common.skip('Could not read v8.h'); + return; +} + +// Exclude a number of checks that make sense on the C++ side but have +// much faster/better JS equivalents, so they should not be exposed. +const exclude = [ + 'Undefined', 'Null', 'NullOrUndefined', 'True', 'False', 'Name', 'String', + 'Symbol', 'Function', 'Array', 'Object', 'Boolean', 'Number', 'Int32', + 'Uint32' +]; + +const start = v8_h.indexOf('Value : public Data'); +const end = v8_h.indexOf('};', start); +const valueDefinition = v8_h.substr(start, end - start); + +const re = /bool Is(\w+)\(\)/g; +let match; +while (match = re.exec(valueDefinition)) { + if (exclude.includes(match[1])) + continue; + assert(`is${match[1]}` in types, + `util.types should provide check for Is${match[1]}`); +} |