UNPKG

@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
"use strict"; 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;