Guest User

Untitled

a guest
Oct 22nd, 2017
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.41 KB | None | 0 0
  1. (function (bn, $) {
  2. var MAIN_MODULE_ID = ""; // per commonjs modules 2.0 draft browser environment's main module identifier should be empty string
  3. var MODULE_ROOT_PATH = "";
  4. var mainModuleDir;
  5. var requireMemo;
  6. var pendingDeclarations;
  7. var scriptTagMemo;
  8. var modulesMemo;
  9. var loadingMemo;
  10. var loadListeners;
  11. var scriptTagEls = []; // keep track of the elements we insert so that when we want to reset we can remove them
  12.  
  13. ///#region Helper functions
  14. /**
  15. * Extract the directory portion of a path
  16. */
  17. function dirname(path) {
  18. if (typeof path !== "string") {
  19. throw new TypeError("dirname expects path to be a string.");
  20. }
  21.  
  22. // remove trailing slash
  23. if (path.charAt(path.length - 1) === '/') {
  24. return path.slice(0, -1);
  25. }
  26.  
  27. // split and remove last part from array and rejoin
  28. var s = path.split('/').slice(0, -1).join('/');
  29.  
  30. // if empty, return current working directory
  31. if (!s) {
  32. return ".";
  33. }
  34.  
  35. return s;
  36. }
  37.  
  38. /** Canonicalize path, compacting slashes and dots per basic UNIX rules.
  39. * Treats paths with trailing slashes as though they end with INDEX instead.
  40. * Not rigorous.
  41. */
  42. function getIdFromPath(path) {
  43. if (typeof path !== "string") {
  44. path = path.toString();
  45. }
  46.  
  47. var oldPath = path.split('/');
  48. var newPath = [];
  49.  
  50. for (var i = 0; i < oldPath.length; i++) {
  51. if (oldPath[i] == '.' || !oldPath[i].length) {
  52. continue;
  53. }
  54. if (oldPath[i] == '..') {
  55. if (!newPath.length) {
  56. throw new Error("Invalid module path: " + path);
  57. }
  58. newPath.pop();
  59. continue;
  60. }
  61. newPath.push(oldPath[i]);
  62. }
  63.  
  64. // not going to prefix w/ slash
  65. // since the location of the source is not referenced absolutely
  66. // because we serve files off of filesystem not http
  67. // newPath.unshift('');
  68.  
  69. return newPath.join('/') || null;
  70. }
  71.  
  72. function makeModuleId(relativeModuleDir, moduleIdentifier) {
  73. if (moduleIdentifier === MAIN_MODULE_ID) {
  74. return MAIN_MODULE_ID;
  75. }
  76.  
  77. if (typeof moduleIdentifier !== "string") {
  78. throw new Error("Invalid module identifier: " + moduleIdentifier);
  79. }
  80.  
  81. var id;
  82. if (moduleIdentifier.indexOf("./") === 0 || moduleIdentifier.indexOf("../") === 0) {
  83. id = relativeModuleDir + "/" + moduleIdentifier;
  84. } else {
  85. id = MODULE_ROOT_PATH + "/" + moduleIdentifier;
  86. }
  87. return getIdFromPath(id);
  88. }
  89.  
  90. function urlToId(moduleURL, relaxValidation) {
  91. var id = moduleURL;
  92. var i;
  93.  
  94. if ((i = id.indexOf('?')) !== -1) {
  95. id = id.slice(0, i);
  96. }
  97.  
  98. if ((i = id.indexOf('#')) !== -1) {
  99. id = id.slice(0, i);
  100. }
  101.  
  102. if (!relaxValidation && (id.slice(-3) !== ".js")) {
  103. throw new Error("Invalid module URL: " + moduleURL);
  104. }
  105.  
  106. id = id.slice(0, -3);
  107.  
  108. return id;
  109. }
  110.  
  111. function idsFromIdentifiers(identifiers, startingModuleId) {
  112. var startingModuleDir = dirname(startingModuleId);
  113. return identifiers.map(function (identifier) {
  114. return makeModuleId(startingModuleDir, identifier);
  115. });
  116. }
  117.  
  118. function addLoadListener(uri, listener) {
  119. if (loadListeners.hasOwnProperty(uri)) {
  120. loadListeners[uri].push(listener);
  121. } else {
  122. loadListeners[uri] = [listener];
  123. }
  124. }
  125.  
  126. function fireLoadListeners(uri) {
  127. if (loadListeners.hasOwnProperty(uri)) {
  128. loadListeners[uri].forEach(function (listener) {
  129. listener(uri);
  130. });
  131. }
  132. }
  133.  
  134. function loadScript(uri, onLoaded, onError) {
  135. if (document.head.querySelector('script[src^="' + uri + '"]') === null) {
  136. var el = document.createElement("script");
  137.  
  138. if (typeof onLoaded === "function") {
  139. el.addEventListener("load", function onScriptLoad() {
  140. onLoaded();
  141. fireLoadListeners(uri);
  142. el.removeEventListener("load", onScriptLoad);
  143. });
  144. }
  145. if (typeof onError === "function") {
  146. el.addEventListener("error", function onScriptError() {
  147. onError();
  148. fireLoadListeners(uri);
  149. el.removeEventListener("error", onScriptError);
  150. });
  151. }
  152.  
  153. el.src = MainApp.hasInspector() ? uri + '?___________________________________ts_=' + (new Date().getTime()) : uri;
  154. document.head.appendChild(el);
  155.  
  156. scriptTagEls.push(el);
  157. } else {
  158. throw new Error("[BN::REQUIRE] loadScript was called for " + uri + "; however, the script was already in the DOM.");
  159. }
  160. }
  161. //#endregion
  162.  
  163. //#region require namespace implementation
  164. function requireFactory(moduleDir, dependencies) {
  165. var require = function (moduleIdentifier) {
  166. var id = makeModuleId(moduleDir, moduleIdentifier);
  167.  
  168. if (!requireMemo[id] && pendingDeclarations[id]) {
  169. initializeModule(id);
  170. }
  171.  
  172. if (id === null || !requireMemo[id]) {
  173. throw new Error("Module {0} has not been provided and is not available.".format(id));
  174. }
  175.  
  176. return requireMemo[id];
  177.  
  178. };
  179.  
  180. require.id = function (moduleIdentifier) {
  181. return makeModuleId(moduleDir, moduleIdentifier);
  182. };
  183.  
  184. require.uri = function (moduleIdentifier) {
  185. var id = makeModuleId(moduleDir, moduleIdentifier);
  186. if (id === null) {
  187. throw new Error("Require could not create id from module identifier passed in: " + moduleIdentifier);
  188. }
  189.  
  190. return id + ".js";
  191. }
  192.  
  193. require.memoize = function requireMemoize(id, dependencies, moduleFactory) {
  194. pendingDeclarations[id] = { moduleFactory: moduleFactory, dependencies: dependencies };
  195. };
  196.  
  197. require.isMemoized = function requireIsMemoized(id) {
  198. return (pendingDeclarations[id] || requireMemo[id]) ? true : false;
  199. };
  200.  
  201. return require;
  202. }
  203. //#endregion
  204.  
  205. function packagesFromDependencies(dependencies) {
  206. return dependencies
  207. .filter(function (moduleId) {
  208. return moduleId.indexOf('packages/') === 0;
  209. })
  210. .map(function (moduleId) {
  211. var packageName = moduleId.split('/')[1];
  212. if (!packageName) {
  213. throw new Error('invalid package name in module id ' + moduleId);
  214. }
  215. return packageName;
  216. });
  217. }
  218.  
  219. /**
  220. * loads each dependency module one at a time, when all done,
  221. * when all dependencies are loaded, the callback is invoked (if passed in)
  222. *
  223. * NB! for packages that are required, but filtered out because they are being loaded, we should listen for when that module has been provided so that callback can guarantee all require calls
  224. *
  225. * TODO! still needs to be fully implemented, for now, we will only load packages
  226. */
  227. function provide(dependencies, onProvided) {
  228. var packages = packagesFromDependencies(dependencies).filter(function (packageName) { !bn.packageLoader.isBeingLoaded(packageName); });
  229.  
  230. if (packages.length > 0) {
  231. bn.packageLoader.ready(packages, onProvided);
  232. } else {
  233. onProvided();
  234. }
  235. }
  236.  
  237. //#region Module namespace implementation
  238. function provideModule(dependencies, moduleFactory, id, callback) {
  239. /* Memoize the the factory, satistfy the dependencies, and invoke the callback */
  240. if (moduleFactory) {
  241. bn.require.memoize(id, dependencies, moduleFactory);
  242. }
  243.  
  244. if (dependencies) {
  245. bn.module.provide(dependencies, callback);
  246. } else {
  247. if (callback) {
  248. callback();
  249. }
  250. }
  251. }
  252.  
  253. function makeModuleForId(id) {
  254. var dependencies = pendingDeclarations[id].dependencies;
  255. return new NobleJSModule(id, dependencies);
  256. }
  257.  
  258. function initializeModule(id) {
  259. var moduleDirectory = id ? dirname(id) : MODULE_ROOT_PATH;
  260. var moduleFactory = pendingDeclarations[id].moduleFactory;
  261. var dependencies = pendingDeclarations[id].dependencies;
  262.  
  263. // create context aware require from factory method
  264. var require = requireFactory(moduleDirectory, dependencies);
  265. var exports = requireMemo[id] = {};
  266. var module = id === MAIN_MODULE_ID ? bn.module : modulesMemo[id];
  267.  
  268. var factoryResult = moduleFactory(require, exports, module);
  269. // if module does not return anything use our exports object, otherwise exported api is the factory's returned result
  270. requireMemo[id] = factoryResult === undefined
  271. ? exports
  272. : factoryResult;
  273.  
  274. delete pendingDeclarations[id];
  275. }
  276.  
  277. function initializeMainModule(dependencies, moduleFactory) {
  278. if (bn.module.main) {
  279. throw new Error("bn Main module has already been created!");
  280. }
  281.  
  282. bn.require.memoize(MAIN_MODULE_ID, dependencies, moduleFactory);
  283.  
  284. function requireMainModule() {
  285. bn.module.constructor.prototype.main = bn.require(MAIN_MODULE_ID);
  286. }
  287.  
  288. provideModule(dependencies, moduleFactory, MAIN_MODULE_ID, requireMainModule);
  289. }
  290.  
  291. function NobleJSModule(id, dependencies) {
  292. this.id = id;
  293. this.dependencies = dependencies;
  294. }
  295.  
  296.  
  297. // Be careful not to assign NobleJS.prototype directly because of the following phenomenon:
  298. // function F() { }
  299. // F.prototype = {};
  300. // var f = new F();
  301. // f.constructor.prototype.main = "something";
  302. // for (var i in { a: 1, b: 2 }) { console.log(i); }
  303. // This outputs "a", "b", "main"!!
  304. NobleJSModule.prototype.declare = function bnModuleDeclare(dependencies, moduleFactory) {
  305. if (typeof dependencies === "function") {
  306. moduleFactory = dependencies;
  307. dependencies = [];
  308. }
  309.  
  310. if (!bn.module.main) { // first time called, we declare this module as the main module
  311. initializeMainModule(dependencies, moduleFactory);
  312. } else { // otherwise script-inserted module
  313. scriptTagMemo = { moduleFactory: moduleFactory, dependencies: dependencies };
  314. }
  315. };
  316.  
  317. NobleJSModule.prototype.define = function bnModuleDefine(id, factoryMethod) {
  318. if (typeof factoryMethod !== "function") {
  319. throw new Error("module.define must be passed a factory method.");
  320. }
  321.  
  322. bn.require.memoize(id, [], factoryMethod);
  323. modulesMemo[id] = new NobleJSModule(id, []);
  324. initializeModule(id);
  325. };
  326.  
  327. NobleJSModule.prototype.load = function bnModuleLoad(moduleIdentifier, onModuleLoaded) {
  328. var js = bn.require.uri(moduleIdentifier);
  329. var id = urlToId(js);
  330.  
  331. loadingMemo[id] = {};
  332.  
  333. loadScript(
  334. js,
  335. function onModuleFileLoaded() {
  336. if (scriptTagMemo) {
  337. // TODO: use provideModule
  338. var moduleDependencies = scriptTagMemo.dependencies;
  339. bn.require.memoize(id, scriptTagMemo.dependencies, scriptTagMemo.moduleFactory);
  340.  
  341. scriptTagMemo = null;
  342. delete loadingMemo[id];
  343.  
  344. modulesMemo[id] = makeModuleForId(id);
  345.  
  346. if (moduleDependencies.length > 0) {
  347. modulesMemo[id].provide(moduleDependencies, onModuleLoaded);
  348. } else {
  349. onModuleLoaded();
  350. }
  351. } else {
  352. throw new Error("module.declare was not used inside module js file: {0}".format(js));
  353. }
  354. },
  355. function onError() {
  356. onModuleLoaded();
  357. }
  358. );
  359. };
  360.  
  361. function isMemoizedOrIsLoading(id) {
  362. return bn.require.isMemoized(id) || loadingMemo.hasOwnProperty(id);
  363. }
  364.  
  365. NobleJSModule.prototype.provide = function (dependencyIdentifiers, onProvided) {
  366. if (dependencyIdentifiers.length === 0) {
  367. onProvided();
  368. return;
  369. }
  370.  
  371. var loadedSoFar = [];
  372. function onLoaded(id) {
  373. loadedSoFar.push(id);
  374.  
  375. if (loadedSoFar.length === dependencyIds.length) {
  376. onProvided();
  377. }
  378. }
  379. var load = this.load.bind(this);
  380.  
  381. var dependencyIds = idsFromIdentifiers(dependencyIdentifiers, this.id);
  382. dependencyIds.forEach(function (id) {
  383. // NOTE: we don't do a .filter, because execution of the loop body could change the memoization status of this module.
  384. if (!isMemoizedOrIsLoading(id)) {
  385. load(id, function () { onLoaded(id); });
  386. } else if (bn.require.isMemoized(id)) {
  387. onLoaded(id);
  388. } else {
  389. var uri = bn.require.uri(id);
  390. addLoadListener(uri, function onScriptLoaded() { onLoaded(id); });
  391. }
  392. });
  393. };
  394. //#endregion
  395.  
  396. bn.resetNobleJS = function (injectedMainModuleDir) {
  397. if (!injectedMainModuleDir) {
  398. if (mainModuleDir) {
  399. injectedMainModuleDir = mainModuleDir;
  400. } else {
  401. injectedMainModuleDir = dirname(urlToId(window.location.href + ".js", true));
  402. }
  403. }
  404.  
  405. requireMemo = {};
  406. modulesMemo = {};
  407. loadingMemo = {};
  408. loadListeners = {};
  409. pendingDeclarations = {};
  410.  
  411. scriptTagEls.forEach(function (el) {
  412. document.head.removeChild(el);
  413. });
  414. scriptTagEls.length = 0;
  415.  
  416. bn.module = new NobleJSModule(MAIN_MODULE_ID, []);
  417. bn.module.constructor.prototype.main = null;
  418.  
  419. // create global bn require
  420. bn.require = requireFactory(MODULE_ROOT_PATH, []);
  421.  
  422. bn.require.factory = function (url) { // TODO: why??
  423. return requireFactory(dirname(url));
  424. };
  425.  
  426. // debug directory helper
  427. bn.require.__dir__ = function () {
  428. console.dir(Object.keys(requireMemo).concat(Object.keys(pendingDeclarations)));
  429. };
  430. }
  431.  
  432. bn.resetNobleJS();
  433.  
  434. // provide default modules
  435. $.extend(requireMemo, {
  436. bn: bn,
  437. "bn/event": bn.event
  438. });
  439. } (bn, jQuery));
Add Comment
Please, Sign In to add comment