From b6aa18be58034c88bcfb00cfd78eae335a52a98c Mon Sep 17 00:00:00 2001 From: James Ide Date: Mon, 11 May 2015 04:17:03 -0700 Subject: [PATCH] [io.js] Update jsdom and get jest working on io.js This gets jest working on io.js 1.8.x and 2.0.x. io.js is reconciling with the Node Foundation so users who are still on Node are on the upgrade path that converges with io.js anyway. What this means is the jest version probably should be bumped to 0.5.0, where 0.4.x is a maintenance branch for legacy Node (typically with semver, a major version bump is required but 0.x.x releases are considered a free-for-all). This diff is near the minimal amount of work to bring jest up to date and pass all of its tests. - Upgraded npm dependencies. The major update is jsdom from 0.10.3 to 5.4.3. This lets us drop the indirect contextify dependency. - Removed harmonize, since io.js uses modern V8 and enables stable ES6 features by default - Removed the `--harmony` flag from the TestRunner for the same reason (trivia: i added that line once upon a time, let me delete it) - Replaced jsdom's `run` with io.js's built-in `vm` module - Added support for curried arguments in the fake `nextTick` implementation, which io.js itself relies on - Updated the HasteModuleLoader to handle Node built-in modules before `node_modules` -- this fixes an issue I was getting with graceful-fs trying to require smalloc. - Patched coffeescript to use Array.isArray instead of `instanceof Array`. Working on getting that merged upstream. Test Plan: ``` nvm install iojs-1 rm -fr node_modules && npm install nvm install iojs-2 rm -fr node_modules && npm install ``` --- .travis.yml | 3 +- bin/jest.js | 3 -- package.json | 34 ++++++++++------------ src/HasteModuleLoader/HasteModuleLoader.js | 21 +++++-------- src/JSDomEnvironment.js | 11 +++++-- src/TestRunner.js | 1 - src/jasmineTestRunner/JasmineReporter.js | 8 +---- src/jasmineTestRunner/jasmineTestRunner.js | 9 ------ src/lib/FakeTimers.js | 14 +++++++-- 9 files changed, 46 insertions(+), 58 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9144899aff6b..e8536f5a4d7c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: node_js node_js: -- "0.10" +- "iojs-v1" +- "iojs-v2" sudo: false diff --git a/bin/jest.js b/bin/jest.js index 29c528413edb..12baa245116f 100755 --- a/bin/jest.js +++ b/bin/jest.js @@ -10,7 +10,6 @@ 'use strict'; var fs = require('fs'); -var harmonize = require('harmonize'); var optimist = require('optimist'); var path = require('path'); @@ -36,8 +35,6 @@ function _wrapDesc(desc) { }, ['']).join(indent); } -harmonize(); - var argv = optimist .usage('Usage: $0 [--config=] [TestPathRegExp]') .options({ diff --git a/package.json b/package.json index c8ac59d28c6d..2edd164c2edb 100644 --- a/package.json +++ b/package.json @@ -4,32 +4,30 @@ "version": "0.4.5", "main": "src/jest.js", "dependencies": { - "coffee-script": "^1.8.0", - "cover": "~0.2.8", - "diff": "~1.0.4", - "graceful-fs": "^2.0.3", - "harmonize": "1.4.2", - "istanbul": "^0.3.2", - "jasmine-only": "0.1.0", - "jasmine-pit": "~2.0.0", - "jsdom": "~0.10.3", + "coffee-script": "ide/coffeescript#array-check", + "cover": "^0.2.9", + "diff": "^1.4.0", + "graceful-fs": "^3.0.7", + "istanbul": "^0.3.14", + "jasmine-only": "^0.1.1", + "jasmine-pit": "^2.0.2", + "jsdom": "^5.4.2", "node-haste": "^1.2.8", - "node-worker-pool": "~2.4.2", - "optimist": "~0.6.0", - "q": "~0.9.7", - "resolve": "~0.6.1", - "through": "^2.3.4", - "lodash.template": "^3.0.0" + "node-worker-pool": "^2.4.4", + "optimist": "^0.6.1", + "q": "^1.4.1", + "resolve": "^1.1.6", + "through": "^2.3.7" }, "devDependencies": { - "jshint": "~2.5.0", - "node-find-files": "0.0.2" + "jshint": "^2.7.0", + "node-find-files": "0.0.4" }, "bin": { "jest": "./bin/jest.js" }, "engines": { - "node": "0.8.x || 0.10.x" + "node": ">= 1" }, "repository": { "type": "git", diff --git a/src/HasteModuleLoader/HasteModuleLoader.js b/src/HasteModuleLoader/HasteModuleLoader.js index 9b1a3d7a8f14..8b3958c4f749 100644 --- a/src/HasteModuleLoader/HasteModuleLoader.js +++ b/src/HasteModuleLoader/HasteModuleLoader.js @@ -129,15 +129,6 @@ function Loader(config, environment, resourceMap) { this._configShouldMockModuleNames = {}; if (_configUnmockListRegExpCache === null) { - // Node must have been run with --harmony in order for WeakMap to be - // available prior to version 0.12 - if (typeof WeakMap !== 'function') { - throw new Error( - 'Please run node with the --harmony flag! jest requires WeakMap ' + - 'which is only available with the --harmony flag in node < v0.12' - ); - } - _configUnmockListRegExpCache = new WeakMap(); } @@ -862,14 +853,14 @@ Loader.prototype.requireModule = function(currPath, moduleName, modulePath = manualMockResource.path; } - if (!modulePath) { - modulePath = this._moduleNameToPath(currPath, moduleName); - } - if (NODE_CORE_MODULES[moduleName]) { return require(moduleName); } + if (!modulePath) { + modulePath = this._moduleNameToPath(currPath, moduleName); + } + // Always natively require the jasmine runner. if (modulePath.indexOf(VENDOR_PATH) === 0) { return require(modulePath); @@ -1037,6 +1028,10 @@ Loader.prototype.resetModuleRegistry = function() { this._environment.fakeTimers.runAllTicks(); }.bind(this), + runAllImmediates: function() { + this._environment.fakeTimers.runAllImmediates(); + }.bind(this), + runAllTimers: function() { this._environment.fakeTimers.runAllTimers(); }.bind(this), diff --git a/src/JSDomEnvironment.js b/src/JSDomEnvironment.js index a6efe560f926..cd7ad52a090d 100644 --- a/src/JSDomEnvironment.js +++ b/src/JSDomEnvironment.js @@ -9,6 +9,8 @@ var FakeTimers = require('./lib/FakeTimers'); +var vm = require('vm'); + function _deepCopy(obj) { var newObj = {}; var value; @@ -29,7 +31,8 @@ function JSDomEnvironment(config) { // use it (depending on the context -- such as TestRunner.js when operating as // a workerpool parent), this is the best way to ensure we only spend time // require()ing this when necessary. - this.global = require('./lib/jsdom-compat').jsdom().parentWindow; + this.global = require('./lib/jsdom-compat').jsdom().defaultView; + this.global.window = this.global; // Node's error-message stack size is limited at 10, but it's pretty useful to // see more than that when a test fails. @@ -52,7 +55,6 @@ function JSDomEnvironment(config) { this.global.Uint32Array = Uint32Array; this.global.DataView = DataView; this.global.Buffer = Buffer; - this.global.process = process; this.global.setImmediate = setImmediate; this.global.clearImmediate = clearImmediate; @@ -105,7 +107,10 @@ JSDomEnvironment.prototype.dispose = function() { }; JSDomEnvironment.prototype.runSourceText = function(sourceText, fileName) { - return this.global.run(sourceText, fileName); + var sandbox = vm.createContext(this.global); + return vm.runInContext(sourceText, sandbox, { + filename: fileName, + }); }; JSDomEnvironment.prototype.runWithRealTimers = function(cb) { diff --git a/src/TestRunner.js b/src/TestRunner.js index b574db01d4d4..23b36bf41cdf 100644 --- a/src/TestRunner.js +++ b/src/TestRunner.js @@ -494,7 +494,6 @@ TestRunner.prototype._createParallelTestRun = function( this._opts.maxWorkers, this._opts.nodePath, this._opts.nodeArgv.concat([ - '--harmony', TEST_WORKER_PATH, '--config=' + JSON.stringify(this._config) ]) diff --git a/src/jasmineTestRunner/JasmineReporter.js b/src/jasmineTestRunner/JasmineReporter.js index 17720e965a02..a0ee9d5be26b 100644 --- a/src/jasmineTestRunner/JasmineReporter.js +++ b/src/jasmineTestRunner/JasmineReporter.js @@ -201,14 +201,7 @@ JasmineReporter.prototype._prettyPrint = function(obj, indent, cycleWeakMap) { ')'; } - /* jshint camelcase:false */ if (!cycleWeakMap) { - if (typeof WeakMap !== 'function') { - throw new Error( - 'Please run node with the --harmony flag! jest requires WeakMap ' + - 'which is only available with the --harmony flag in node < v0.12' - ); - } cycleWeakMap = new WeakMap(); } @@ -231,6 +224,7 @@ JasmineReporter.prototype._prettyPrint = function(obj, indent, cycleWeakMap) { this._prettyPrint(value, indent + keyIndent, cycleWeakMap) ); } + /* jshint camelcase:false */ delete obj.__jstest_pp_cycle__; return '{\n' + keysOutput.join(',\n') + '\n' + indent + '}'; } else { diff --git a/src/jasmineTestRunner/jasmineTestRunner.js b/src/jasmineTestRunner/jasmineTestRunner.js index 701771b420a3..f92f940f1d0d 100644 --- a/src/jasmineTestRunner/jasmineTestRunner.js +++ b/src/jasmineTestRunner/jasmineTestRunner.js @@ -54,15 +54,6 @@ function jasmineTestRunner(config, environment, moduleLoader, testPath) { // Install jasmine-only environment.runSourceText(jasmineOnlyContent); - // Node must have been run with --harmony in order for WeakMap to be - // available prior to version 0.12 - if (typeof WeakMap !== 'function') { - throw new Error( - 'Please run node with the --harmony flag! jest requires WeakMap ' + - 'which is only available with the --harmony flag in node < v0.12' - ); - } - // Mainline Jasmine sets __Jasmine_been_here_before__ on each object to // detect cycles, but that doesn't work on frozen objects so we use a // WeakMap instead. diff --git a/src/lib/FakeTimers.js b/src/lib/FakeTimers.js index c03c4bb218be..059aa64dc941 100644 --- a/src/lib/FakeTimers.js +++ b/src/lib/FakeTimers.js @@ -315,10 +315,18 @@ FakeTimers.prototype._fakeClearImmediate = function(uuid) { }; FakeTimers.prototype._fakeNextTick = function(callback) { + var args = []; + for (var ii = 1, ll = arguments.length; ii < ll; ii++) { + args.push(arguments[ii]); + } + var uuid = this._uuidCounter++; + this._ticks.push({ uuid: uuid, - callback: callback + callback: function() { + return callback.apply(null, args); + } }); var cancelledTicks = this._cancelledTicks; @@ -326,7 +334,7 @@ FakeTimers.prototype._fakeNextTick = function(callback) { if (!cancelledTicks.hasOwnProperty(uuid)) { // Callback may throw, so update the map prior calling. cancelledTicks[uuid] = true; - callback(); + callback.apply(null, args); } }); }; @@ -351,7 +359,7 @@ FakeTimers.prototype._fakeSetImmediate = function(callback) { if (!cancelledImmediates.hasOwnProperty(uuid)) { // Callback may throw, so update the map prior calling. cancelledImmediates[uuid] = true; - callback(); + callback.apply(null, args); } });