Skip to content
This repository was archived by the owner on Aug 3, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,79 @@ modules.require(
// module 'A' now resolved to a
});
````

####Дополнение к YModules####

В дополнение сделана возможность обработать возможность догрузки модуля по имени, если такого модуля в системе не зарегистированно. В функцию loadModules будет передан массив имен модулей, которые необходимо загрузить. После того как все модули будут загружены, необходимо вызвать функцию обратного вызова.

````javascript
modules.setOptions({
/**
* Функция поиска модуля
*
* @param {String} moduleName Имя модуля, который не зарегистирован в системе
* @return {Boolean} Можно ли этот модуль загрузить
*/
findDep: function( moduleName ) {
// body...
},
/**
* Функция срабатывает, если функция findDep вернула true.
*
* @param {Array} moduleNames Массив имен модулей, которые необходимо загрузить
* @param {Function} callback Функция обратного вызова
*/
loadModules: function( moduleName, callback ) {
// body...
}
});
````

####Пример с загрузкой модуля####

Допустим, у нас есть внешняя утилита, которая умеет составлять объекты соотвествия имен модулей файлам в которых они находятся. В качестве загрузчка используется [LAB.js](http://labjs.com/).

````javascript
var modulesDep = {"storage":"core.js", "menu": "ui.js"};

// Настройки LAB.js
$LAB.setGlobalDefaults({
AllowDuplicates: false,
AlwaysPreserveOrder: true,
UseLocalXHR: false,
BasePath: '/javascripts/'
});

// Настраиваем поиск и загрузку незарегистрированных модулей
modules.setOptions({
findDep: function( moduleName ) {
return modulesDep.hasOwnProperty(moduleName);
},
loadModules: function( modulesNames, callback ) {
var
loadedCnt = 0,
filename,
i;
// end of vars

for ( i = 0; i < modulesNames.length; i++ ) {
filename = modulesDep[modulesNames[i]];

(function(f) {
$LAB.script( getWithVersion(f) ).wait(function() {
loadedCnt++;

if (loadedCnt === modulesNames.length) callback();
});
}(filename));
}
}
});


modules.require(
['storage'],
function( s ) {
// module 'storage' now resolved to 's'
});
````
45 changes: 32 additions & 13 deletions modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,26 +161,45 @@ var undef,
cb(exports);
}
},
i = 0, len = unresolvedDepsCnt,
dep, decl;
unloadedDeps = [],
i = 0, j = 0, len = unresolvedDepsCnt,
dep, decl,

while(i < len) {
dep = deps[i++];
require = function() {

while(i < len) {
dep = deps[i++];
if(typeof dep === 'string') {
decl = modulesStorage[dep].decl;
}
else {
decl = dep;
}

decls.push(decl);

startDeclResolving(decl, path, onDeclResolved);
}
};

while(j < len) {
dep = deps[j++];
if(typeof dep === 'string') {
if(!modulesStorage[dep]) {
if(!modulesStorage[dep] && typeof curOptions.findDep === 'function' && typeof curOptions.loadModules === 'function' && curOptions.findDep(dep)) {
unloadedDeps.push(dep);
}
else if(!modulesStorage[dep]) {
cb(null, buildModuleNotFoundError(dep, fromDecl));
return;
}

decl = modulesStorage[dep].decl;
}
else {
decl = dep;
}
}

decls.push(decl);

startDeclResolving(decl, path, onDeclResolved);
if(unloadedDeps.length) {
curOptions.loadModules(unloadedDeps, require);
}
else {
require();
}
},

Expand Down
37 changes: 37 additions & 0 deletions modules/A.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* @param {Object} modules
*/
!function ( modules, undefined ) {
'use strict';

var
/**
* @param {Function} provide Async module export
*/
module = function ( provide ) {
var
/**
* // moduleRealization description
*/
moduleRealization = function() {
return 100;
};
// end of vars

provide(moduleRealization);
};
// end of vars


/**
* @module A
* @version 0.1
*/
modules.define(
'A', // Module name
[], // Dependies
module // Module realization
);
}(
( this.hasOwnProperty('modules') ) ? this.modules : modules
);
40 changes: 40 additions & 0 deletions modules/B.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* @param {Object} modules
*/
!function ( modules, undefined ) {
'use strict';

var
/**
* @param {Function} provide Async module export
*/
module = function ( provide, A, C ) {
var
resultA = A(),
resultC = C(),

/**
* // moduleRealization description
*/
moduleRealization = function() {
return 100 + resultA + resultC;
};
// end of vars

provide(moduleRealization);
};
// end of vars


/**
* @module B
* @version 0.1
*/
modules.define(
'B', // Module name
['A', 'C'], // Dependies
module // Module realization
);
}(
( this.hasOwnProperty('modules') ) ? this.modules : modules
);
37 changes: 37 additions & 0 deletions modules/C.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* @param {Object} modules
*/
!function ( modules, undefined ) {
'use strict';

var
/**
* @param {Function} provide Async module export
*/
module = function ( provide ) {
var
/**
* // moduleRealization description
*/
moduleRealization = function() {
return 200;
};
// end of vars

provide(moduleRealization);
};
// end of vars


/**
* @module C
* @version 0.1
*/
modules.define(
'C', // Module name
[], // Dependies
module // Module realization
);
}(
( this.hasOwnProperty('modules') ) ? this.modules : modules
);
56 changes: 56 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,62 @@ describe('resolving', function() {
});
});

describe('load modules', function() {
it('should properly load module and resolve dependencies', function(done) {
var
modulesDep = {'A': './modules/A.js', 'B': './modules/B.js', 'C': './modules/C.js'};

// Настраиваем поиск и загрузку незарегистрированных модулей
modules.setOptions({
findDep: function( moduleName ) {
return modulesDep.hasOwnProperty(moduleName);
},
loadModules: function( modulesNames, callback ) {
var
fs = require('fs'),
vm = require('vm'),
loadedCnt = 0,

// Proxy
originalRequire = require,
processProcess = process,

filename, file, context, script, i;

for(i = 0; i < modulesNames.length; i++) {
filename = modulesDep[modulesNames[i]];
(function(filename){
file = fs.readFile(filename, 'utf8', function(err, data) {
context = vm.createContext({
process: processProcess,
require: originalRequire,
modules: modules,
console: console,
exports: exports,
module: {
exports: exports
}
});
script = vm.createScript(data, filename);
script.runInNewContext(context);

loadedCnt++;

if (loadedCnt === modulesNames.length) callback();
});
}(filename))
};
}
});

modules.require(['B'], function(B) {
var res = B();
res.should.have.been.equal(400);
done();
});
});
});

describe('errors', function() {
it('should throw error on requiring undefined module', function(done) {
modules.require(['A'], function() {}, function(e) {
Expand Down