@extjs/sencha-cmd-linux-32
Version:
Productivity and performance optimization tool for building applications with Sencha Ext JS and Sencha Touch.
333 lines (269 loc) • 10.6 kB
JavaScript
;
var Fashion = require('../export/Base.js');
var Preprocessor = require('../Preprocessor.js');
var Nodes = require('../parse/ast/Nodes.js');
var ExportTypes = require('../export/type/Types.js');
var ExportRuntime = require('../export/Runtime.js');
var CssVariableManager = require('../export/css/CssVariableManager.js');
CssVariableManager = new CssVariableManager();
class IndexGenerator {
constructor () {
this.ids = [];
this.index = 0;
}
_getIndexes (ids) {
var len = ids.length || 1,
chars = this.chars,
clen = len == 1 ? chars.length - 10 : chars.length,
out = [],
prefix;
for (var i = 0; i < len; i++) {
for (var j = 0; j < clen; j++) {
prefix = (ids[i] || '') + chars[j];
if (prefix === 'as' || prefix === 'do' || prefix === 'if' || prefix === 'in') {
continue;
}
out.push(prefix);
}
}
return out;
}
next () {
var me = this;
if (me.index < me.ids.length) {
return me.ids[me.index++];
}
me.index = 0;
me.ids = me._getIndexes(me.ids);
return me.next();
}
}
var chars = IndexGenerator.prototype.chars = ['_', '$'];
for (var i = 65; i < 91; i++){
chars.push(String.fromCharCode(i));
chars.push(String.fromCharCode(i + 32));
}
chars.push.call(chars, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
class ExportBuilder {
constructor (defaultRuleset) {
this.defaultRuleset = defaultRuleset;
}
instrumentObject (registered, called, isFn) {
var instrumented = {};
Object.getOwnPropertyNames(registered).forEach(function(key){
var fn = registered[key];
instrumented[key] = function(){
called[key] = {
func: fn,
isFn: isFn
};
return fn.apply(registered, arguments);
};
});
return instrumented;
}
buildExportFn (variables) {
var me = this,
runtime = this.runtime,
setterAst = me.createSettersAst(variables),
preprocessor = new Preprocessor({
runtime: runtime
}),
newContext = new runtime.context.constructor({
preprocessor: preprocessor
}),
allVariables = Fashion.chain(runtime.context.preprocessor.variables),
setterVariables, sortedAst, settersCode, settersFunc;
preprocessor.enableElevationWarning = false;
preprocessor.sortAllVariables = (this.export === 'all');
preprocessor.loadPreprocessorCache(runtime.context.preprocessor);
preprocessor.reset = function(){};
preprocessor.preprocess(setterAst, true);
setterVariables = preprocessor.getVariables();
Fashion.apply(allVariables, setterVariables);
preprocessor.variables = allVariables;
newContext.dynamicsMap = preprocessor.getDynamicsMap();
sortedAst = preprocessor.getSortedDynamicAstNodes();
settersCode = newContext.transpiler.transpile(sortedAst);
newContext.runtime.setCaches(newContext.transpiler);
var origGet = runtime.constructor.prototype.get,
origRegistered = runtime.registered,
origFunctions = runtime.functions,
registered = origRegistered,
functions = origFunctions,
called = {},
read = {};
runtime.registered = me.instrumentObject(registered, called, false);
runtime.functions = me.instrumentObject(functions, called, true);
runtime.constructor.prototype.get = function(name) {
var result = origGet.apply(this, arguments);
var jsName = Fashion.getJsName(name).replace(/^\$/, '');
if (!variables[jsName]) {
read[jsName] = {
name: jsName,
variable: result
};
}
return result;
};
newContext.runtime.copyRuntimeState(runtime);
settersFunc = newContext.compile(settersCode);
// execute the generated fn to detect the needed functions using the
// above instrumented objects
settersFunc(newContext.runtime, null, newContext.dynamicsMap);
runtime.registered = origRegistered;
runtime.functions = origFunctions;
runtime.constructor.prototype.get = origGet;
var keys = Object.getOwnPropertyNames(read);
if (keys.length) {
for (var k = 0; k < keys.length; k++) {
var key = keys[k];
variables[key] = read[key];
}
return me.buildExportFn(variables);
}
var registered = [],
functions = [];
Object.getOwnPropertyNames(called).forEach(function(key){
var value = called[key],
func = called[key].func,
fn = func + '';
fn = fn.replace(/^.*?\(/g, ' function (');
if (!value.isFn) {
registered.push(' ' + key + ': ' + fn);
}
else {
functions.push(' ' + key + ': ' + fn);
}
});
var fnPrefix = [
'(function(Fashion){',
'\tvar __udf = undefined,',
'\t Types = Fashion.Types,',
'\t __strings = {},\n',
'\t __names = Fashion.css.buildNames(__strings),\n',
'\t __jsNames = Fashion.css.buildJsNames(__strings);\n'
].join('\n');
fnPrefix += runtime.createTypesBlock(ExportTypes);
var fnBody = fnPrefix + '\n\tFashion.css.register(function(__rt) {\n';
fnBody += '__rt.register({\n';
fnBody += registered.join(',\n');
fnBody += '\n});\n';
fnBody += runtime.createMethodBlock(ExportRuntime.prototype);
fnBody += runtime.createPropertyBlock();
fnBody += 'Fashion.apply(__rt.functions, {\n';
fnBody += functions.join(',\n')
.replace(/__rt\.registered/, '__rt_registered')
.replace(/__rt\.functions/, '__rt_functions')
.replace(/__rt\.mixins/, '__rt_mixins');
fnBody += '\n});\n';
fnBody += '},\n';
fnBody += ' function(__rt) {\n';
fnBody += runtime.createMethodBlock(ExportRuntime.prototype);
fnBody += runtime.createPropertyBlock();
fnBody += settersCode
.replace(/__rt\.registered/, '__rt_registered')
.replace(/__rt\.functions/, '__rt_functions')
.replace(/__rt\.mixins/, '__rt_mixins') + '\n';
fnBody += '},\n';
return fnBody;
}
createSettersAst (exportedVariables) {
var setters = [];
Object.getOwnPropertyNames(exportedVariables).forEach(function(key){
var exported = exportedVariables[key],
value = exported.variable,
ast;
if (value.$isWrapper) {
value = value.value;
}
ast = value.ast;
if (ast) {
setters.push(new Nodes.VariableAssignment(null, '$' + exported.name, ast));
}
});
return setters;
}
buildExportFunction (exportedVariables, runtime) {
var me = this,
selectorMap = {},
fnBody, keys, i, j, rs, selector,
setters, setter, vars, variable, entry;
me.runtime = runtime;
fnBody = me.buildExportFn(exportedVariables);
keys = Object.getOwnPropertyNames(exportedVariables);
for (i = 0; i < keys.length; i++) {
var key = keys[i],
exported = exportedVariables[key],
rulesets = exported.rulesets;
if (!rulesets && me.defaultRuleset) {
rulesets = [me.defaultRuleset];
}
for (j = 0; j < rulesets.length; j++) {
rs = rulesets[j];
selector = Fashion.SourceBuilder.toSource(rs.selectors);
entry = selectorMap[selector] || (selectorMap[selector] = {
vars: [],
name: exported.name
});
entry.vars.push(exported);
}
}
keys = Object.getOwnPropertyNames(selectorMap);
fnBody += ' {\n';
setters = [];
for (i = 0; i < keys.length; i++) {
setter = '';
key = keys[i];
entry = selectorMap[key];
vars = entry.vars;
setter += '\t' + JSON.stringify(key) + ': [\n';
for (j = 0; j < vars.length; j++) {
if (j > 0) {
setter += ',\n';
}
variable = vars[j];
setter += '\t\t' + JSON.stringify(variable.name);
}
setter += '\n\t]';
setters.push(setter);
}
fnBody += setters.join(',\n');
fnBody += '});\n})(Fashion);';
var keys = [],
regex = /__rt_set\("(.+?)"/g,
name, jsName, match;
while (match = regex.exec(fnBody)) {
keys.push(match[1]);
}
keys.sort(function(a, b){
return a.length - b.length;
});
var strings = {},
map = {},
idGen = new IndexGenerator(),
prefix;
for (var i = 0; i < keys.length; i++) {
key = keys[i];
if (!map[key]) {
map[key] = true;
prefix = idGen.next();
strings[prefix] = key;
name = CssVariableManager.buildName(key);
jsName = CssVariableManager.buildJsName(key);
var keyRx = new RegExp('"\\' + key + '"|\'\\' + key + "'", 'g'),
nameRx = new RegExp('"' + name + '"|\'' + name + "'", 'g'),
jsNameRx = new RegExp('"\\' + jsName + '"|\'\\' + jsName + "'", 'g');
fnBody = fnBody
.replace(keyRx, '__strings.' + prefix)
.replace(nameRx, '__names.' + prefix)
.replace(jsNameRx, '__jsNames.' + prefix);
}
}
map = JSON.stringify(strings, null, 4);
map = map.replace(/"(.*?)":(.*?)(,?)/g, '$1:$2$3');
fnBody = fnBody.replace('__strings = {},', '__strings = ' + map + ',');
return fnBody;
}
}
module.exports = ExportBuilder;