summaryrefslogtreecommitdiff
path: root/test/parallel/test-util-types.js
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2018-01-27 22:01:32 +0100
committerAnna Henningsen <anna@addaleax.net>2018-03-05 17:41:26 +0000
commitb20af8088a4d5cccb1901d42107f6d9ca82d306f (patch)
treed443fa727be877dc7ad6e4112503944a8e674490 /test/parallel/test-util-types.js
parentbd6e0be0dfbbf6d10f1f054c43b0b82f25c60b16 (diff)
downloadandroid-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.js162
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]}`);
+}