Make circular require()'s and exception.
Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/commit/775c526a Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/tree/775c526a Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/diff/775c526a Branch: refs/heads/master Commit: 775c526a34c8de969e8ae82026584950874689d7 Parents: 2e6cb6e Author: Andrew Grieve <agri...@chromium.org> Authored: Mon Aug 20 14:05:03 2012 -0400 Committer: Anis Kadri <anis.ka...@gmail.com> Committed: Fri Aug 24 13:49:58 2012 -0700 ---------------------------------------------------------------------- lib/scripts/require.js | 21 +++++++++++++++++++-- test/test.require.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/775c526a/lib/scripts/require.js ---------------------------------------------------------------------- diff --git a/lib/scripts/require.js b/lib/scripts/require.js index 5ae09e2..9736dad 100644 --- a/lib/scripts/require.js +++ b/lib/scripts/require.js @@ -3,6 +3,10 @@ var require, (function () { var modules = {}; + // Stack of moduleIds currently being built. + var requireStack = []; + // Map of module ID -> index into requireStack of modules currently being built. + var inProgressModules = {}; function build(module) { var factory = module.factory; @@ -15,8 +19,21 @@ var require, require = function (id) { if (!modules[id]) { throw "module " + id + " not found"; + } else if (id in inProgressModules) { + var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id; + throw "Cycle in require graph: " + cycle; } - return modules[id].factory ? build(modules[id]) : modules[id].exports; + if (modules[id].factory) { + try { + inProgressModules[id] = requireStack.length; + requireStack.push(id); + return build(modules[id]); + } finally { + delete inProgressModules[id]; + requireStack.pop(); + } + } + return modules[id].exports; }; define = function (id, factory) { @@ -40,4 +57,4 @@ var require, if (typeof module === "object" && typeof require === "function") { module.exports.require = require; module.exports.define = define; -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/incubator-cordova-js/blob/775c526a/test/test.require.js ---------------------------------------------------------------------- diff --git a/test/test.require.js b/test/test.require.js index b79dec4..566ae05 100644 --- a/test/test.require.js +++ b/test/test.require.js @@ -35,6 +35,38 @@ describe("require + define", function () { }).toThrow("module your mom not found"); }); + it("throws an exception when modules depend on each other", function () { + define("ModuleA", function(require, exports, module) { + require("ModuleB"); + }); + define("ModuleB", function(require, exports, module) { + require("ModuleA"); + }); + expect(function () { + require("ModuleA"); + }).toThrow("Cycle in require graph: ModuleA->ModuleB->ModuleA"); + define.remove("ModuleA"); + define.remove("ModuleB"); + }); + + it("throws an exception when a cycle of requires occurs", function () { + define("ModuleA", function(require, exports, module) { + require("ModuleB"); + }); + define("ModuleB", function(require, exports, module) { + require("ModuleC"); + }); + define("ModuleC", function(require, exports, module) { + require("ModuleA"); + }); + expect(function () { + require("ModuleA"); + }).toThrow("Cycle in require graph: ModuleA->ModuleB->ModuleC->ModuleA"); + define.remove("ModuleA"); + define.remove("ModuleB"); + define.remove("ModuleC"); + }); + it("calls the factory method when requiring", function () { var factory = jasmine.createSpy(); define("dino", factory);