blob: b96ce400c74b89ed422d9d755e07c3b4ed36d8b5 [file] [log] [blame]
// Copyright 2013 The Closure Library Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview A nodejs script for dynamically requiring Closure within
* nodejs.
*
* Example of usage:
* <code>
* require('./bootstrap/nodejs')
* goog.require('goog.ui.Component')
* </code>
*
* This loads goog.ui.Component in the global scope.
*
* If you want to load custom libraries, you can require the custom deps file
* directly. If your custom libraries introduce new globals, you may
* need to run goog.nodeGlobalRequire to get them to load correctly.
*
* <code>
* require('./path/to/my/deps.js')
* goog.bootstrap.nodeJs.nodeGlobalRequire('./path/to/my/base.js')
* goog.require('my.Class')
* </code>
*
* @author nick@medium.com (Nick Santos)
*
* @nocompile
*/
var fs = require("fs");
var vm = require("vm");
var path = require("path");
var CLJS_ROOT = ".";
/**
* The goog namespace in the global scope.
*/
global.goog = {};
/**
* Imports a script using Node's require() API.
*
* @param {string} src The script source.
* @return {boolean} True if the script was imported, false otherwise.
*/
global.CLOSURE_IMPORT_SCRIPT = function(src, opt_sourceText) {
// if CLJS_ROOT has been rewritten (by REPLs) need to compute require path
// so we can delete the old entry from the Node.js require cache
if(CLJS_ROOT !== ".") {
var cached = null;
if(src.substring(0, 2) == "..") {
cached = path.join(CLJS_ROOT, src.substring(3));
} else {
cached = path.join(CLJS_ROOT, "goog", src);
}
if(require.cache[cached]) delete require.cache[cached];
}
// Sources are always expressed relative to closure's base.js, but
// require() is always relative to the current source.
if (opt_sourceText === undefined) {
var flags = null;
if (goog.debugLoader_) {
var dep = goog.debugLoader_.dependencies_[src];
if (dep) {
flags = dep.loadFlags;
}
} else {
flags = goog.dependencies_.loadFlags[src];
}
if (flags && flags["foreign-lib"]) {
nodeGlobalRequire(path.resolve(__dirname, "..", src));
} else {
require(path.join(".", "..", src));
}
} else {
eval(opt_sourceText);
}
return true;
};
/**
* Loads a file when using Closure's goog.require() API with goog.modules.
*
* @param {string} src The file source.
* @return {string} The file contents.
*/
global.CLOSURE_LOAD_FILE_SYNC = function(src) {
return fs.readFileSync(
path.resolve(__dirname, '..', src), {encoding: 'utf-8'});
};
// Declared here so it can be used to require base.js
function nodeGlobalRequire(file) {
var _module = global.module,
_exports = global.exports,
exportedRequire = false;
// to circumvent Node.js environment detection in bundled libraries
global.module = undefined;
global.exports = undefined;
// to allow requires of Node.js libraries (i.e. platform libs) that
// couldn't be bundled for some reason
if(global.require == undefined) {
exportedRequire = true;
global.require = require;
}
vm.runInThisContext.call(global, fs.readFileSync(file), file);
global.exports = _exports;
global.module = _module;
if(exportedRequire) {
global.require = undefined;
}
}
// Load Closure's base.js into memory. It is assumed base.js is in the
// directory above this directory given this script's location in
// bootstrap/nodejs.js.
nodeGlobalRequire(path.resolve(__dirname, '..', 'base.js'));
/**
* Bootstraps a file into the global scope.
*
* This is strictly for cases where normal require() won't work,
* because the file declares global symbols with 'var' that need to
* be added to the global scope.
* @suppress {missingProvide}
*
* @param {string} file The path to the file.
*/
goog.nodeGlobalRequire = nodeGlobalRequire;