|
@@ -43,36 +43,70 @@ function always_resolve(callback) {
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Helper for concatenation modules and producing output
|
|
|
|
- * that can be actually run.
|
|
|
|
|
|
+ * Helper for concatenating Amber generated AMD modules.
|
|
|
|
+ * The produced output can be exported and run as an independent program.
|
|
|
|
+ *
|
|
|
|
+ * var concatenator = createConcatenator();
|
|
|
|
+ * concatenator.start(); // write the required AMD define header
|
|
|
|
+ * concatenator.add(module1);
|
|
|
|
+ * concatenator.addId(module1_ID);
|
|
|
|
+ * //...
|
|
|
|
+ * concatenator.finish("//some last code");
|
|
|
|
+ * var concatenation = concatenator.toString();
|
|
|
|
+ * // The variable concatenation contains the concatenated result
|
|
|
|
+ * // which can either be stored in a file or interpreted with eval().
|
|
*/
|
|
*/
|
|
-function makeBuilder () {
|
|
|
|
- var defineDefine = function () {
|
|
|
|
|
|
+function createConcatenator () {
|
|
|
|
+ var defineAmdDefine = function () {
|
|
var path = require('path');
|
|
var path = require('path');
|
|
- return ($SRC$)(module);
|
|
|
|
|
|
+ return ($AMDEFINE_SRC$)(module);
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ // The createAmdefineString is hack to help injecting amdefine into the concatenated output.
|
|
|
|
+ //
|
|
|
|
+ // Usually, the line 'var define = require('amdefine')(module), requirejs = define.require;'
|
|
|
|
+ // is needed when using amdefine with node and npm installed.
|
|
|
|
+ // var f = require('amdefine') itself returns one big self-sufficient function which must be called
|
|
|
|
+ // as f(module) to get the define you can use.
|
|
|
|
+ //
|
|
|
|
+ // However, amdefine needs the definition of the 'path' variable (node's internal 'path' module).
|
|
|
|
+ // To create this dependency the defineAmdDefine() function is used which defines
|
|
|
|
+ // the path variable first and adds a placeholder for the amdefine function/sourcecode.
|
|
|
|
+ // The defineAmdDefine() function is then converted to its string representation
|
|
|
|
+ // and the placeholder is replaced with the actual sourcecode of the amdefine function.
|
|
|
|
+ var createAmdefineString = function() {
|
|
|
|
+ return ('' + defineAmdDefine).replace('$AMDEFINE_SRC$', '' + require('amdefine'));
|
|
|
|
+ }
|
|
|
|
+
|
|
return {
|
|
return {
|
|
elements: [],
|
|
elements: [],
|
|
ids: [],
|
|
ids: [],
|
|
- add: function () { this.elements.push.apply(this.elements, arguments); },
|
|
|
|
- addId: function () { this.ids.push.apply(this.ids, arguments); },
|
|
|
|
- forEach: function () { this.elements.forEach.apply(this.elements, arguments); },
|
|
|
|
|
|
+ add: function () {
|
|
|
|
+ this.elements.push.apply(this.elements, arguments);
|
|
|
|
+ },
|
|
|
|
+ addId: function () {
|
|
|
|
+ this.ids.push.apply(this.ids, arguments);
|
|
|
|
+ },
|
|
|
|
+ forEach: function () {
|
|
|
|
+ this.elements.forEach.apply(this.elements, arguments);
|
|
|
|
+ },
|
|
start: function () {
|
|
start: function () {
|
|
this.add(
|
|
this.add(
|
|
- 'var define = ('+(''+defineDefine).replace('$SRC$', ""+require('amdefine'))+')(), requirejs = define.require;',
|
|
|
|
|
|
+ 'var define = (' + createAmdefineString() + ')(), requirejs = define.require;',
|
|
'define("amber_vm/browser-compatibility", [], {});'
|
|
'define("amber_vm/browser-compatibility", [], {});'
|
|
);
|
|
);
|
|
},
|
|
},
|
|
finish: function (realWork) {
|
|
finish: function (realWork) {
|
|
this.add(
|
|
this.add(
|
|
- 'define("amber_vm/_init", ["amber_vm/smalltalk","'+this.ids.join('","')+'"], function (smalltalk) {',
|
|
|
|
|
|
+ 'define("amber_vm/_init", ["amber_vm/smalltalk","' + this.ids.join('","') + '"], function (smalltalk) {',
|
|
'smalltalk.initialize();',
|
|
'smalltalk.initialize();',
|
|
realWork,
|
|
realWork,
|
|
'});', 'requirejs("amber_vm/_init");'
|
|
'});', 'requirejs("amber_vm/_init");'
|
|
);
|
|
);
|
|
},
|
|
},
|
|
- toString: function () { return this.elements.join('\n'); }
|
|
|
|
|
|
+ toString: function () {
|
|
|
|
+ return this.elements.join('\n');
|
|
|
|
+ }
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
@@ -81,27 +115,27 @@ function makeBuilder () {
|
|
* Taken from: http://howtonode.org/control-flow
|
|
* Taken from: http://howtonode.org/control-flow
|
|
*/
|
|
*/
|
|
function Combo(callback) {
|
|
function Combo(callback) {
|
|
- this.callback = callback;
|
|
|
|
- this.items = 0;
|
|
|
|
- this.results = [];
|
|
|
|
|
|
+ this.callback = callback;
|
|
|
|
+ this.items = 0;
|
|
|
|
+ this.results = [];
|
|
}
|
|
}
|
|
|
|
|
|
Combo.prototype = {
|
|
Combo.prototype = {
|
|
- add: function () {
|
|
|
|
- var self = this,
|
|
|
|
|
|
+ add: function () {
|
|
|
|
+ var self = this,
|
|
id = this.items;
|
|
id = this.items;
|
|
- this.items++;
|
|
|
|
- return function () {
|
|
|
|
- self.check(id, arguments);
|
|
|
|
- };
|
|
|
|
- },
|
|
|
|
- check: function (id, arguments) {
|
|
|
|
- this.results[id] = Array.prototype.slice.call(arguments);
|
|
|
|
- this.items--;
|
|
|
|
- if (this.items == 0) {
|
|
|
|
- this.callback.apply(this, this.results);
|
|
|
|
|
|
+ this.items++;
|
|
|
|
+ return function () {
|
|
|
|
+ self.check(id, arguments);
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ check: function (id, arguments) {
|
|
|
|
+ this.results[id] = Array.prototype.slice.call(arguments);
|
|
|
|
+ this.items--;
|
|
|
|
+ if (this.items == 0) {
|
|
|
|
+ this.callback.apply(this, this.results);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
};
|
|
};
|
|
|
|
|
|
var path = require('path'),
|
|
var path = require('path'),
|
|
@@ -135,7 +169,6 @@ var createDefaults = function(amber_dir, finished_callback){
|
|
|
|
|
|
return {
|
|
return {
|
|
'load': [],
|
|
'load': [],
|
|
-// 'init': path.join(amber_dir, 'js', 'init.js'),
|
|
|
|
'main': undefined,
|
|
'main': undefined,
|
|
'mainfile': undefined,
|
|
'mainfile': undefined,
|
|
'stFiles': [],
|
|
'stFiles': [],
|
|
@@ -199,9 +232,6 @@ AmberC.prototype.check_configuration_ok = function(configuration) {
|
|
if (undefined === configuration) {
|
|
if (undefined === configuration) {
|
|
throw new Error('AmberC.check_configuration_ok(): missing configuration object');
|
|
throw new Error('AmberC.check_configuration_ok(): missing configuration object');
|
|
}
|
|
}
|
|
- if (undefined === configuration.init) {
|
|
|
|
-// throw new Error('AmberC.check_configuration_ok(): init value missing in configuration object');
|
|
|
|
- }
|
|
|
|
|
|
|
|
if (0 === configuration.jsFiles.length && 0 === configuration.stFiles.lenght) {
|
|
if (0 === configuration.jsFiles.length && 0 === configuration.stFiles.lenght) {
|
|
throw new Error('AmberC.check_configuration_ok(): no files to compile/link specified in configuration object');
|
|
throw new Error('AmberC.check_configuration_ok(): no files to compile/link specified in configuration object');
|
|
@@ -259,10 +289,12 @@ AmberC.prototype.check_for_closure_compiler = function(callback) {
|
|
*/
|
|
*/
|
|
AmberC.prototype.resolve_js = function(filename, callback) {
|
|
AmberC.prototype.resolve_js = function(filename, callback) {
|
|
var special = filename[0] == "@";
|
|
var special = filename[0] == "@";
|
|
- if (special) { filename = filename.slice(1); }
|
|
|
|
|
|
+ if (special) {
|
|
|
|
+ filename = filename.slice(1);
|
|
|
|
+ }
|
|
var baseName = path.basename(filename, '.js');
|
|
var baseName = path.basename(filename, '.js');
|
|
var jsFile = baseName + this.defaults.loadsuffix + '.js';
|
|
var jsFile = baseName + this.defaults.loadsuffix + '.js';
|
|
- var amberJsFile = path.join(this.amber_dir, special?'js/lib':'js', jsFile);
|
|
|
|
|
|
+ var amberJsFile = path.join(this.amber_dir, (special ? 'js/lib' : 'js'), jsFile);
|
|
console.log('Resolving: ' + jsFile);
|
|
console.log('Resolving: ' + jsFile);
|
|
fs.exists(jsFile, function(exists) {
|
|
fs.exists(jsFile, function(exists) {
|
|
if (exists) {
|
|
if (exists) {
|
|
@@ -364,7 +396,7 @@ AmberC.prototype.resolve_libraries = function() {
|
|
// Resolve libraries listed in this.kernel_libraries
|
|
// Resolve libraries listed in this.kernel_libraries
|
|
var self = this;
|
|
var self = this;
|
|
var all_resolved = new Combo(function(resolved_kernel_files, resolved_compiler_files) {
|
|
var all_resolved = new Combo(function(resolved_kernel_files, resolved_compiler_files) {
|
|
- self.resolve_init(resolved_compiler_files[0]);
|
|
|
|
|
|
+ self.create_compiler(resolved_compiler_files[0]);
|
|
});
|
|
});
|
|
this.resolve_kernel(all_resolved.add());
|
|
this.resolve_kernel(all_resolved.add());
|
|
this.resolve_compiler(all_resolved.add());
|
|
this.resolve_compiler(all_resolved.add());
|
|
@@ -424,23 +456,6 @@ AmberC.prototype.resolve_compiler = function(callback) {
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
-/**
|
|
|
|
- * Resolves default.init and adds it to compilerFiles.
|
|
|
|
- * Followed by create_compiler().
|
|
|
|
- */
|
|
|
|
-AmberC.prototype.resolve_init = function(compilerFiles) {
|
|
|
|
- // check and add init.js
|
|
|
|
-// var initFile = this.defaults.init;
|
|
|
|
-// if ('.js' !== path.extname(initFile)) {
|
|
|
|
-// initFile = this.resolve_js(initFile);
|
|
|
|
-// this.defaults.init = initFile;
|
|
|
|
-// }
|
|
|
|
-// compilerFiles.push(initFile);
|
|
|
|
-
|
|
|
|
- this.create_compiler(compilerFiles);
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* Read all .js files needed by compiler and eval() them.
|
|
* Read all .js files needed by compiler and eval() them.
|
|
* The finished Compiler gets stored in defaults.smalltalk.
|
|
* The finished Compiler gets stored in defaults.smalltalk.
|
|
@@ -449,16 +464,20 @@ AmberC.prototype.resolve_init = function(compilerFiles) {
|
|
AmberC.prototype.create_compiler = function(compilerFilesArray) {
|
|
AmberC.prototype.create_compiler = function(compilerFilesArray) {
|
|
var self = this;
|
|
var self = this;
|
|
var compiler_files = new Combo(function() {
|
|
var compiler_files = new Combo(function() {
|
|
- var builder = makeBuilder();
|
|
|
|
|
|
+ var builder = createConcatenator();
|
|
builder.add('(function() {');
|
|
builder.add('(function() {');
|
|
builder.start();
|
|
builder.start();
|
|
|
|
|
|
Array.prototype.slice.call(arguments).forEach(function(data) {
|
|
Array.prototype.slice.call(arguments).forEach(function(data) {
|
|
// data is an array where index 0 is the error code and index 1 contains the data
|
|
// data is an array where index 0 is the error code and index 1 contains the data
|
|
builder.add(data[1]);
|
|
builder.add(data[1]);
|
|
- var match = (""+data[1]).match(/^define\("([^"]*)"/);
|
|
|
|
- if (match) builder.addId(match[1]);
|
|
|
|
|
|
+ // matches and returns the "module_id" string in the AMD definition: define("module_id", ...)
|
|
|
|
+ var match = ('' + data[1]).match(/^define\("([^"]*)"/);
|
|
|
|
+ if (match) {
|
|
|
|
+ builder.addId(match[1]);
|
|
|
|
+ }
|
|
});
|
|
});
|
|
|
|
+ // store the generated smalltalk env in self.defaults.smalltalk
|
|
builder.finish('self.defaults.smalltalk = smalltalk;');
|
|
builder.finish('self.defaults.smalltalk = smalltalk;');
|
|
builder.add('})();');
|
|
builder.add('})();');
|
|
eval(builder.toString());
|
|
eval(builder.toString());
|
|
@@ -614,11 +633,6 @@ AmberC.prototype.compose_js_files = function() {
|
|
program_files.push.apply(program_files, compiledFiles);
|
|
program_files.push.apply(program_files, compiledFiles);
|
|
}
|
|
}
|
|
|
|
|
|
- if (undefined !== defaults.init) {
|
|
|
|
-// console.log('Adding initializer ' + defaults.init);
|
|
|
|
-// program_files.push(defaults.init);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
console.ambercLog('Writing program file: %s.js', programFile);
|
|
console.ambercLog('Writing program file: %s.js', programFile);
|
|
|
|
|
|
var fileStream = fs.createWriteStream(programFile + defaults.suffix_used + '.js');
|
|
var fileStream = fs.createWriteStream(programFile + defaults.suffix_used + '.js');
|
|
@@ -631,15 +645,18 @@ AmberC.prototype.compose_js_files = function() {
|
|
self.optimize();
|
|
self.optimize();
|
|
});
|
|
});
|
|
|
|
|
|
- var builder = makeBuilder();
|
|
|
|
|
|
+ var builder = createConcatenator();
|
|
builder.start();
|
|
builder.start();
|
|
|
|
|
|
program_files.forEach(function(file) {
|
|
program_files.forEach(function(file) {
|
|
if(fs.existsSync(file)) {
|
|
if(fs.existsSync(file)) {
|
|
console.log('Adding : ' + file);
|
|
console.log('Adding : ' + file);
|
|
var buffer = fs.readFileSync(file);
|
|
var buffer = fs.readFileSync(file);
|
|
|
|
+ // matches and returns the "module_id" string in the AMD define: define("module_id", ...)
|
|
var match = buffer.toString().match(/^define\("([^"]*)"/);
|
|
var match = buffer.toString().match(/^define\("([^"]*)"/);
|
|
- if (match /*&& match[1].slice(0,9) !== "amber_vm/"*/) { builder.addId(match[1]); }
|
|
|
|
|
|
+ if (match /*&& match[1].slice(0,9) !== "amber_vm/"*/) {
|
|
|
|
+ builder.addId(match[1]);
|
|
|
|
+ }
|
|
builder.add(buffer);
|
|
builder.add(buffer);
|
|
} else {
|
|
} else {
|
|
fileStream.end();
|
|
fileStream.end();
|
|
@@ -647,22 +664,25 @@ AmberC.prototype.compose_js_files = function() {
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
- var realWork = '';
|
|
|
|
|
|
+ var mainFunctionOrFile = '';
|
|
|
|
|
|
if (undefined !== defaults.main) {
|
|
if (undefined !== defaults.main) {
|
|
console.log('Adding call to: %s>>main', defaults.main);
|
|
console.log('Adding call to: %s>>main', defaults.main);
|
|
- realWork += 'smalltalk.' + defaults.main + '._main();';
|
|
|
|
|
|
+ mainFunctionOrFile += 'smalltalk.' + defaults.main + '._main();';
|
|
}
|
|
}
|
|
|
|
|
|
if (undefined !== defaults.mainfile && fs.existsSync(defaults.mainfile)) {
|
|
if (undefined !== defaults.mainfile && fs.existsSync(defaults.mainfile)) {
|
|
console.log('Adding main file: ' + defaults.mainfile);
|
|
console.log('Adding main file: ' + defaults.mainfile);
|
|
- realWork += '\n' + fs.readFileSync(defaults.mainfile);
|
|
|
|
|
|
+ mainFunctionOrFile += '\n' + fs.readFileSync(defaults.mainfile);
|
|
}
|
|
}
|
|
|
|
|
|
- builder.finish(realWork);
|
|
|
|
|
|
+ builder.finish(mainFunctionOrFile);
|
|
|
|
|
|
console.log('Writing...');
|
|
console.log('Writing...');
|
|
- builder.forEach(function (element) { fileStream.write(element); fileStream.write('\n'); });
|
|
|
|
|
|
+ builder.forEach(function (element) {
|
|
|
|
+ fileStream.write(element);
|
|
|
|
+ fileStream.write('\n');
|
|
|
|
+ });
|
|
console.log('Done.');
|
|
console.log('Done.');
|
|
fileStream.end();
|
|
fileStream.end();
|
|
};
|
|
};
|