| 'use strict'; |
| const common = require('../../common'); |
| const fs = require('fs'); |
| const assert = require('assert'); |
| |
| // Addon is referenced through the eval expression in testFile |
| const addon = require(`./build/${common.buildType}/test_general`); |
| const path = require('path'); |
| |
| // This test depends on a number of V8 tests. |
| const v8TestsDir = path.resolve(__dirname, '..', '..', '..', 'deps', 'v8', |
| 'test', 'mjsunit'); |
| const v8TestsDirExists = fs.existsSync(v8TestsDir); |
| |
| // The following assert functions are referenced by v8's unit tests |
| // See for instance deps/v8/test/mjsunit/instanceof.js |
| // eslint-disable-next-line no-unused-vars |
| function assertTrue(assertion) { |
| return assert.strictEqual(assertion, true); |
| } |
| |
| // eslint-disable-next-line no-unused-vars |
| function assertFalse(assertion) { |
| assert.strictEqual(assertion, false); |
| } |
| |
| // eslint-disable-next-line no-unused-vars |
| function assertEquals(leftHandSide, rightHandSide) { |
| assert.strictEqual(leftHandSide, rightHandSide); |
| } |
| |
| // eslint-disable-next-line no-unused-vars |
| function assertThrows(statement) { |
| assert.throws(function() { |
| eval(statement); |
| }, Error); |
| } |
| |
| function testFile(fileName) { |
| try { |
| const contents = fs.readFileSync(fileName, { encoding: 'utf8' }); |
| eval(contents.replace(/[(]([^\s(]+)\s+instanceof\s+([^)]+)[)]/g, |
| '(addon.doInstanceOf($1, $2))')); |
| } catch (err) { |
| // This test depends on V8 test files, which may not exist in downloaded |
| // archives. Emit a warning if the tests cannot be found instead of failing. |
| if (err.code === 'ENOENT' && !v8TestsDirExists) |
| process.emitWarning(`test file ${fileName} does not exist.`); |
| else |
| throw err; |
| } |
| } |
| |
| testFile(path.join(v8TestsDir, 'instanceof.js')); |
| testFile(path.join(v8TestsDir, 'instanceof-2.js')); |
| |
| // We can only perform this test if we have a working Symbol.hasInstance |
| if (typeof Symbol !== 'undefined' && 'hasInstance' in Symbol && |
| typeof Symbol.hasInstance === 'symbol') { |
| |
| function compareToNative(theObject, theConstructor) { |
| assert.strictEqual( |
| addon.doInstanceOf(theObject, theConstructor), |
| (theObject instanceof theConstructor) |
| ); |
| } |
| |
| function MyClass() {} |
| Object.defineProperty(MyClass, Symbol.hasInstance, { |
| value: function(candidate) { |
| return 'mark' in candidate; |
| } |
| }); |
| |
| function MySubClass() {} |
| MySubClass.prototype = new MyClass(); |
| |
| let x = new MySubClass(); |
| let y = new MySubClass(); |
| x.mark = true; |
| |
| compareToNative(x, MySubClass); |
| compareToNative(y, MySubClass); |
| compareToNative(x, MyClass); |
| compareToNative(y, MyClass); |
| |
| x = new MyClass(); |
| y = new MyClass(); |
| x.mark = true; |
| |
| compareToNative(x, MySubClass); |
| compareToNative(y, MySubClass); |
| compareToNative(x, MyClass); |
| compareToNative(y, MyClass); |
| } |