UNPKG

atom-nuclide

Version:

A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.

115 lines (99 loc) 4.3 kB
'use strict'; /* @noflow */ /* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ /* NON-TRANSPILED FILE */ /* eslint-disable babel/func-params-comma-dangle, prefer-object-spread/prefer-object-spread */ //------------------------------------------------------------------------------ // FOR DEVELOPMENT USE ONLY // // This module monkey-patches Atom's babel compiler so that we can apply custom // transforms on Nuclide code only. The alternative is to run a watcher and // always run transpiled code in Atom. As "clean" as that solution is, watchers // require setting up, and are a departure from how the Atom development // ecosystem works. Monkey-patching lets developers work on Nuclide in the same // way as any other Atom package. The day this approach stops working, we'll // re-evaluate the watcher. // // The additional transforms applied here are only optimizations. Nuclide code // should be able to run on a stock Atom w/o these transforms. This ensures that // the hackery done here doesn't break future Nuclide compatibility with Atom, // or tooling like flow and eslint. It also keeps cowboy devs at bay from // introducing exotic syntax, stage 0 features, and/or obscene module systems // like Haste. //------------------------------------------------------------------------------ const assert = require('assert'); const path = require('path'); const NodeTranspiler = require('../../pkg/nuclide-node-transpiler/lib/NodeTranspiler'); const nuclideBasedir = path.join(require.resolve('../../package.json'), '../'); assert(path.isAbsolute(nuclideBasedir)); assert(nuclideBasedir.endsWith(path.sep)); function isNuclideFile(filename) { return filename.startsWith(nuclideBasedir); } //--- let nodeTranspiler; try { // Atom's babel-core may already be in the require cache if a module before us // needed "use babel" transpilation. There is no guarantee that that has // happened yet. require.resolve it so we fail fast if it ever goes missing. // // We could use Nuclide's own babel-core (even babel 6), but we want the exact // babel Atom would use in a stock setup- to be able to fallback to Atom // transpiling if needed. const babelVersion = require(path.join( process.resourcesPath, 'app.asar/node_modules/babel-core/package.json' )).version; const babelPath = require.resolve(path.join( process.resourcesPath, 'app.asar/node_modules/babel-core' )); nodeTranspiler = new NodeTranspiler(babelVersion, () => require(babelPath)); } catch (err) { throw new Error('babel-core was not found'); } //--- // "babel.js" is the wrapper around Babel used by Atom. It is loaded during // Atom's initial setup- before any "~/.atom/packages". // https://github.com/atom/atom/blob/v1.6.2/src/babel.js let babelCompiler; try { // The babel compiler is in the require cache, but use require so we fail // fast if it ever goes missing. babelCompiler = require(path.join(process.resourcesPath, 'app.asar/src/babel.js')); } catch (err) { throw new Error('babel.js was not found'); } const _real_shouldCompile = babelCompiler.shouldCompile; babelCompiler.shouldCompile = function(sourceCode, filePath) { const actual = NodeTranspiler.shouldCompile(sourceCode); const expected = _real_shouldCompile.call(this, sourceCode, filePath); // Verify that our own "shouldCompile" is matching Atom. assert(actual === expected); return actual; }; const _real_getCachePath = babelCompiler.getCachePath; babelCompiler.getCachePath = function(sourceCode, filePath) { if (isNuclideFile(filePath)) { const configDigest = nodeTranspiler.getConfigDigest(); const fileDigest = nodeTranspiler.getFileDigest(sourceCode, filePath); const cachePath = path.join('js/nuclide', configDigest, fileDigest + '.js'); return cachePath; } else { return _real_getCachePath.call(this, sourceCode, filePath); } }; const _real_compile = babelCompiler.compile; babelCompiler.compile = function(sourceCode, filePath) { if (isNuclideFile(filePath)) { return nodeTranspiler.transformWithCache(sourceCode, filePath); } else { return _real_compile.call(this, sourceCode, filePath); } };