├── .editorconfig ├── .gitignore ├── .jscsrc ├── .jshintrc ├── .travis.yml ├── LICENSE.txt ├── README.md ├── bin └── traceur-runner.js ├── lib └── traceur-runner.js ├── package.json └── test ├── cases ├── local-deps.js ├── no-deps.js ├── node_modules │ ├── run-with-traceur-o │ │ ├── index.js │ │ └── package.json │ └── run-without-traceur-k │ │ ├── index.js │ │ └── package.json ├── package-deps.js ├── throws-an-error.js └── with-args.js ├── local-deps ├── returns-k.js └── returns-o.js └── test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | charset = utf-8 8 | indent_style = space 9 | indent_size = 4 10 | 11 | [package.json] 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /npm-debug.log 3 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "crockford", 3 | "requireMultipleVarDecl": null, 4 | "disallowDanglingUnderscores": null, 5 | "validateQuoteMarks": "\"" 6 | } 7 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "camelcase": true, 4 | "curly": true, 5 | "eqeqeq": true, 6 | "freeze": true, 7 | "globalstrict": true, 8 | "immed": true, 9 | "indent": 4, 10 | "latedef": "nofunc", 11 | "maxlen": 120, 12 | "newcap": true, 13 | "noarg": true, 14 | "node": true, 15 | "nonbsp": true, 16 | "nonew": true, 17 | "quotmark": "double", 18 | "undef": true, 19 | "unused": true 20 | } 21 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | script: 5 | npm run lint && npm test 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright © 2014 Domenic Denicola 2 | 3 | This work is free. You can redistribute it and/or modify it under the 4 | terms of the Do What The Fuck You Want To Public License, Version 2, 5 | as published by Sam Hocevar. See below for more details. 6 | 7 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 8 | Version 2, December 2004 9 | 10 | Copyright (C) 2004 Sam Hocevar 11 | 12 | Everyone is permitted to copy and distribute verbatim or modified 13 | copies of this license document, and changing it is allowed as long 14 | as the name is changed. 15 | 16 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 17 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 18 | 19 | 0. You just DO WHAT THE FUCK YOU WANT TO. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Run JavaScript.next code in Node, seamlessly 2 | 3 | **Traceur Runner** allows you to run code authored for [Traceur](https://www.npmjs.com/package/traceur) seamlessly in Node.js. It does so by compiling the code on the fly using [Traceur's mechanism for overriding `require`](https://github.com/google/traceur-compiler/wiki/Using-Traceur-with-Node.js), but with some additional smarts. 4 | 5 | In particular, Traceur Runner will avoid compiling any dependent packages (i.e. those found in `node_modules`), *unless* those packages are marked with `"traceur-runner": true` in their `package.json`. This way, you can seamlessly consume most packages without Traceur trying to transpile them, while still getting Traceur compilation for those of your dependencies that are targeted at Traceur themselves. 6 | 7 | Additionally, whenever you use Traceur Runner, you will automatically get all error stacks rewritten to have the correct line and column numbers, via the excellent [traceur-source-maps](https://www.npmjs.com/package/traceur-source-maps) package! 8 | 9 | ## Usage 10 | 11 | You can use `traceur-runner` as a binary, pointing it at some code that needs transpiling: 12 | 13 | ``` 14 | $ traceur-runner my-script.js 15 | ``` 16 | 17 | You can also use command-line arguments: 18 | 19 | ``` 20 | $ traceur-runner my-script.js arg1 arg2 21 | ``` 22 | 23 | If you do this latter, then `my-script.js` will have a `process.argv` such that `"arg1"` is at index `2`, `"arg2"` at index `3`, and so on. 24 | 25 | Finally, you can also use it programmatically: if you do 26 | 27 | ```js 28 | require("traceur-runner"); 29 | ``` 30 | 31 | in your source file, any further `require`s will be transpiled as appropriate. 32 | 33 | ## Traceur Dependency 34 | 35 | Traceur Runner [peer-depends](https://blog.domenic.me/peer-dependencies/) on Traceur, allowing you to use it with whatever version of Traceur you are already using in your project. This means you should add `traceur` as a dependency in your `package.json`, if you haven't already. 36 | -------------------------------------------------------------------------------- /bin/traceur-runner.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | var path = require("path"); 4 | 5 | require("../lib/traceur-runner.js"); 6 | 7 | var filename = path.resolve(process.cwd(), process.argv[2]); 8 | 9 | // Make the args look like ["<...>traceur-runner", "<...>the file", ... args passed] 10 | // This simulates how when you do `node file.js arg1 arg2` you get ["<...>node", "file.js", "arg1", "arg2"] 11 | // i.e. it makes traceur-runner a better substitute for node. 12 | process.argv = process.argv.slice(1); 13 | 14 | require(filename); 15 | -------------------------------------------------------------------------------- /lib/traceur-runner.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var traceur = require("traceur"); 3 | var path = require("path"); 4 | var fs = require("fs"); 5 | 6 | require("traceur-source-maps").install(traceur); 7 | 8 | traceur.require.makeDefault(function (filename) { 9 | var segments = filename.split(/(?:\/|\\)/); 10 | var nodeModulesIndex = segments.lastIndexOf("node_modules"); 11 | if (nodeModulesIndex === -1) { 12 | return true; 13 | } 14 | 15 | var packagePath = segments.slice(0, nodeModulesIndex + 2).join(path.sep) + path.sep + "package.json"; 16 | var packageContents = fs.readFileSync(packagePath, { encoding: "utf-8" }); 17 | var packageJSON = JSON.parse(packageContents); 18 | 19 | return !!packageJSON["traceur-runner"]; 20 | }); 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "traceur-runner", 3 | "description": "Runs JavaScript.next code in Node by compiling it with Traceur on the fly, seamlessly", 4 | "keywords": [ 5 | "traceur", 6 | "es6", 7 | "harmony", 8 | "require" 9 | ], 10 | "version": "2.0.1", 11 | "author": "Domenic Denicola (https://domenic.me/)", 12 | "license": "WTFPL", 13 | "repository": "domenic/traceur-runner", 14 | "main": "lib/traceur-runner.js", 15 | "bin": "bin/traceur-runner.js", 16 | "files": [ 17 | "bin/", 18 | "lib/" 19 | ], 20 | "scripts": { 21 | "test": "mocha test/test.js", 22 | "lint": "jshint lib bin && jscs lib bin" 23 | }, 24 | "dependencies": { 25 | "traceur-source-maps": "^1.0.6" 26 | }, 27 | "peerDependencies": { 28 | "traceur": ">= 0.0.79 < 1" 29 | }, 30 | "devDependencies": { 31 | "child-process-promise": "^1.0.1", 32 | "jscs": "^1.8.1", 33 | "jshint": "^2.5.10", 34 | "mocha": "1.21.4", 35 | "traceur": "0.0.79" 36 | }, 37 | "_dependencyComments": { 38 | "mocha": "keeping at 1.21.4 until https://github.com/mochajs/mocha/issues/1241 is fixed" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/cases/local-deps.js: -------------------------------------------------------------------------------- 1 | import o from "../local-deps/returns-o.js"; 2 | import k from "../local-deps/returns-k.js"; 3 | 4 | console.log(o + k); 5 | -------------------------------------------------------------------------------- /test/cases/no-deps.js: -------------------------------------------------------------------------------- 1 | console.log(`ok`); 2 | -------------------------------------------------------------------------------- /test/cases/node_modules/run-with-traceur-o/index.js: -------------------------------------------------------------------------------- 1 | export default `o`; 2 | -------------------------------------------------------------------------------- /test/cases/node_modules/run-with-traceur-o/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "traceur-runner": true 3 | } 4 | -------------------------------------------------------------------------------- /test/cases/node_modules/run-without-traceur-k/index.js: -------------------------------------------------------------------------------- 1 | // Traceur auto-strictifies any code it takes in, so if this file is Traceurified the result will be `undefined`. 2 | var globalThis = function () { return this; }(); 3 | if (globalThis !== global) { 4 | throw new Error("Traceur wrapping detected in a package that was not marked for Traceur Runner to process"); 5 | } 6 | 7 | module.exports = "k"; 8 | -------------------------------------------------------------------------------- /test/cases/node_modules/run-without-traceur-k/package.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /test/cases/package-deps.js: -------------------------------------------------------------------------------- 1 | import o from "run-with-traceur-o"; 2 | var k = require("run-without-traceur-k"); 3 | 4 | console.log(o + k); 5 | -------------------------------------------------------------------------------- /test/cases/throws-an-error.js: -------------------------------------------------------------------------------- 1 | `Hello`; 2 | 3 | // A few lines later: 4 | 5 | try { 6 | /* comment */ throw new Error("boo!"); 7 | } catch (e) { 8 | console.log(e.stack); 9 | } 10 | -------------------------------------------------------------------------------- /test/cases/with-args.js: -------------------------------------------------------------------------------- 1 | console.log(process.argv[2] + process.argv[3] === '12' ? `ok` : process.argv); 2 | -------------------------------------------------------------------------------- /test/local-deps/returns-k.js: -------------------------------------------------------------------------------- 1 | export default `k`; 2 | -------------------------------------------------------------------------------- /test/local-deps/returns-o.js: -------------------------------------------------------------------------------- 1 | module.exports = `o`; 2 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var path = require("path"); 3 | var childProcess = require("child-process-promise"); 4 | var assert = require("assert"); 5 | 6 | specify("With no dependencies", function () { 7 | return execAndTestOK("no-deps"); 8 | }); 9 | 10 | specify("With local dependencies", function () { 11 | return execAndTestOK("local-deps"); 12 | }); 13 | 14 | specify("With package dependencies", function () { 15 | return execAndTestOK("package-deps"); 16 | }); 17 | 18 | specify("With arguments", function () { 19 | return execAndTestOK("with-args", ["1", "2"]); 20 | }); 21 | 22 | specify("When throwing an error, should use source maps", function () { 23 | return execAndTest("throws-an-error", [], function (stdout) { 24 | assert(stdout.indexOf("throws-an-error.js:6:25") !== -1, 25 | "Must contain the correct error line/column in the stack trace. Got:\n\n" + stdout); 26 | }); 27 | }); 28 | 29 | var binFile = path.resolve(__dirname, "..", require("../package.json").bin); 30 | function execAndTest(testCaseName, args, outputTest) { 31 | if (args === undefined) { 32 | args = []; 33 | } 34 | 35 | // Use relative paths to the CWD, to test that paths relative to the CWD work. 36 | var testFile = path.relative(process.cwd(), path.resolve(__dirname, "cases", testCaseName + ".js")); 37 | return childProcess.execFile(process.execPath, [binFile, testFile].concat(args)).then(function (res) { 38 | outputTest(String(res.stdout)); 39 | assert.strictEqual(String(res.stderr), "", "test " + testCaseName + " should not output to stderr"); 40 | }); 41 | } 42 | 43 | function execAndTestOK(testCaseName, args) { 44 | return execAndTest(testCaseName, args, function (stdout) { 45 | assert.strictEqual(stdout, "ok\n", "test " + testCaseName + " should output the string \"ok\""); 46 | }); 47 | } 48 | --------------------------------------------------------------------------------