UNPKG

@extjs/sencha-cmd-linux-32

Version:

Productivity and performance optimization tool for building applications with Sencha Ext JS and Sencha Touch.

787 lines (651 loc) 20.1 kB
"use strict"; var Fashion = require('./Base.js'), Base = Fashion.Base; var Type = require('./type/Type.js'); var List = require('./type/List.js'); var Bool = require('./type/Bool.js'); var Color = require('./type/Color.js'); var ColorRGBA = require('./type/ColorRGBA.js'); var Text = require('./type/Text.js'); var Literal = require('./type/Literal.js'); var Statics = require('./type/Statics.js'); var TypeVisitor = require('./type/TypeVisitor.js'); var Types = require('./type/Types.js'); class Scope { constructor(prev) { this.prev = prev; this.map = {}; this.sourceInfo = null; } get(name) { var map = this.map, prev = this, value; while (map) { value = map[name]; if (value) { return value; } prev = prev.prev; map = prev && prev.map; } return value; } has(name) { //return name in this.map; var map = this.map, prev = this; while (map) { if (name in map) { return true; } prev = prev.prev; map = prev && prev.map; } return false; } put(name, value) { this.map[name] = value; return value; } addEntries(names) { if (this.prev) { this.prev.addEntries(names); } for (var name in this.map) { names[name] = this.map[name]; } } getEntries(entries) { entries = entries || {}; this.addEntries(entries); return entries; } getSourceInfo() { return this.sourceInfo; } getCallStack(stack) { stack = stack || []; if (this.sourceInfo) { stack.push(this.sourceInfo); } if (this.prev) { this.prev.getCallStack(stack); } return stack; } } Fashion.apply(Scope.prototype, { $isScope: true, map: undefined, prev: undefined, // placeholder used to track what to reset the _currentScope to, resetScope: undefined }); class Runtime extends Base { constructor(config) { super(config); var me = this; me.mixins = {}; me.functions = {}; me.processors = []; me.registered = { runtime: me, box: Statics.boxType, unbox: Statics.unboxType, isArray: function (array) { return Array.isArray(array); }, getRuntime: function () { return this.runtime; }, handleArgs: function (args, keys) { var scope = {}, index = 0, key; for (var a = 0; a < args.length; a++) { var arg = args[a]; if (arg === undefined) { continue; } // Named arguments if (arg === true || arg === false) { scope[keys[index]] = arg; index++; } else if (arg.type === undefined) { for (key in arg) { scope[key.replace(/^\$/, '')] = arg[key]; } } // Required arguments else { key = keys[index]; if (key instanceof Array) { key = key[0]; scope[key] = scope[key] || new List(); scope[key].add(arg); } else { scope[key] = arg; index++; } } } return scope; }, sliceArgs: function (args, start, end) { return this.getRuntime().sliceArgs(args, start, end).items; }, tailArgs: function (start, args) { var tail = Array.prototype.slice.call(args, start); if (tail.length == 1 && this.isArray(tail)) { tail = tail[0]; } return tail; } }; } bool(value) { return new Bool(value); } color(name) { var rgb = Color.map[name], color = new ColorRGBA(rgb[0], rgb[1], rgb[2], rgb[3]); color.stringified = name; return color; } quote(value) { if (value.type === 'string') { return value; } return new Text(value.toString()); } unquote(value) { if (value.$isFashionType) { return value.unquote(); } return new Literal(value.toString()); } not(expression) { return this.box(this.unbox(expression) == false); } operate(operation, left, right) { if (left == null || left.$isFashionNull) { if (operation != '==' && operation != '!=') { return Literal.Null; } } if (right == null || right .$isFashionNull) { if (operation != '==' && operation != '!=') { return Literal.Null; } } return left.operate(operation, right); } reset() { this._currentScope = null; this._currentCallStackScope = this.createCallStackScope(); this._globalScope = this.createScope(); this._dynamics = {}; } run(code, metadata) { this.load(code); this.compile(code); return this.execute(metadata); } createTypesBlock (types) { types = types || this.types; var keys = Object.getOwnPropertyNames(types), buff = [], name; for (var i = 0; i < keys.length; i++) { name = keys[i]; buff.push(name + ' = Types.' + name); buff.push("__" + name + ' = ' + name); } if (buff.length === 0) { return ''; } return 'var ' + buff.join(',\n ') + ';\n'; } createMethodBlock (proto) { proto = proto || this.constructor.prototype; var buff = [], keys, name; while(proto) { keys = Object.getOwnPropertyNames(proto); for (var i = 0; i < keys.length; i++) { name = keys[i]; if (typeof proto[name] === 'function') { buff.push("__rt_" + name + ' = __rt.' + name + '.bind(__rt)'); } } proto = Object.getPrototypeOf(proto); } if (buff.length === 0) { return ''; } return 'var ' + buff.join(',\n ') + ';\n'; } createPropertyBlock() { var keys = Object.getOwnPropertyNames(this), buff = [], name; for (var i = 0; i < keys.length; i++) { name = keys[i]; buff.push("__rt_" + name + ' = __rt.' + name); } if (buff.length === 0) { return ''; } return 'var ' + buff.join(',\n ') + ';\n'; } createPrefixedFunctionBody(code) { code = this.createTypesBlock() + this.createMethodBlock() + this.createPropertyBlock() + code; return code; } createWrappedFn(code) { return new Function('Types', '__rt', '__gs', '__udf', '__dyn', this.createPrefixedFunctionBody(code)); } callWrappedFn(fn, dynamics) { return fn(Fashion, this, this._globalScope, undefined, dynamics || {}); } compile(code) { var me = this, theFn; //code = '"use strict";\n' + code; this.code = code; new Function(); theFn = this.createWrappedFn(code); this.fn = function (rt, overrides, dyn) { var runtime = rt || me, dynamics = dyn || {}; runtime.reset(); if (overrides) { if (overrides.$isScope) { runtime._globalScope = overrides; } else { runtime._globalScope.map = overrides; } } if (dyn) { runtime._dynamics = dyn; } runtime._currentScope = runtime._globalScope; runtime._scopeStack = [runtime._currentScope]; try { theFn(me.types, runtime, runtime._globalScope, undefined, dynamics); } catch (err) { Fashion.raiseAt(err.message || err, null, runtime.getCallStack()); } return runtime._globalScope; }; return this.fn; } execute(metadata) { return this.fn(this, metadata); } load(code) { this.code = code; return this; } registerProcessor(proc) { this.processors.push(new TypeVisitor(proc)); } register(methods) { if (methods['dynamic']) { Fashion.error('Cannot register javascript function named "dynamic"'); delete methods['dynamic']; } if (methods['require']) { Fashion.error('Cannot register javascript function named "require"'); delete methods['require']; } Fashion.apply(this.registered, methods); } isRegistered(name) { name = this.reserved[name] ? '__' + name : name; return !!this.registered[name]; } getGlobalScope() { return this._globalScope; } getCurrentScope() { return this._currentScope; } getRegisteredFunctions() { return this.registered; } getFunctions() { return this.functions; } getMixins() { return this.mixins; } createScope(scope) { var currScope = scope || this._currentScope, newScope = new Scope(currScope); return this.pushScope(newScope); } pushScope(scope) { scope.resetScope = this._currentScope; this._currentScope = scope; return scope; } popScope() { this._currentScope = this._currentScope.resetScope; return this._currentScope; } createCallStackScope(scope) { var currScope = scope || this._currentCallStackScope, newScope = new Scope(currScope); return this.pushCallStackScope(newScope); } pushCallStackScope(scope) { scope.resetScope = this._currentCallStackScope; this._currentCallStackScope = scope; return scope; } popCallStackScope() { this._currentCallStackScope = this._currentCallStackScope.resetScope; return this._currentCallStackScope; } getCallStack() { if (this._currentCallStackScope) { return this._currentCallStackScope.getCallStack(); } return null; } pushSourceInfo(info) { if (this._currentCallStackScope) { this._currentCallStackScope.sourceInfo = info; } return true; } getSourceInfo() { var stack = this._currentCallStackScope, info = stack && stack.sourceInfo; if (info && info.length) { return { lineNumber: info[0], file: info[1] }; } return null; } get(name) { var scope = this.getScopeForName(name), res = scope.map[name]; if (typeof res === 'undefined') { if (!(name in scope.map)) { Fashion.raiseAt('Reference to undeclared variable : ' + name, null, this.getCallStack()); } } return this.box(res); } getScopeForName (jsName) { var scope = this._currentScope; while (scope) { if (jsName in scope.map) { return scope; } scope = scope.prev; } return this._currentScope; } getDefault(val) { if (val == null || typeof val === 'undefined') { // === null || undefined return undefined; } if (val.$isFashionNull) { if (this.constructor.allowNullDefaults) { return val; } return undefined; } return this.box(val); } getGlobalDefault(jsName) { var obj = this._globalScope.get(jsName); return this.getDefault(obj); } getLocalDefault(jsName) { var obj = this._currentScope.get(jsName); return this.getDefault(obj); } setGlobal(jsName, value, astNodeId) { var currScope = this._globalScope; if (!value || !value.$isFashionLiteral) { value = this.box(value); } value.ast = value.ast || this.getAstNode(astNodeId); currScope.map[jsName] = value; return value; } setDynamic(name, value, astNodeId) { var jsName = Fashion.getJsName(name), currScope = this._globalScope, newValue; if (!value || !value.$isFashionLiteral) { value = this.box(value); } value.ast = value.ast || this.getAstNode(astNodeId); if (value.$referenceName || value.$constant) { newValue = value.clone(); newValue.$previousReference = value; value = newValue; value.ast = this.getAstNode(astNodeId); } else { value.$referenceName = name; } currScope.map[jsName] = value; return value; } setScoped (jsName, value) { var currScope = this.getScopeForName(jsName); if (!value || !value.$isFashionLiteral) { value = this.box(value); } currScope.map[jsName] = value; return value; } set (jsName, value) { var currScope = this._currentScope; if (!value || !value.$isFashionLiteral) { value = this.box(value); } currScope.map[jsName] = value; return value; } getDocs(id) { if (this.docCache) { return this.docCache.get(id); } } getString(id) { if (this.stringCache) { return this.stringCache.get(id); } } getAstNode(id) { if (this.nodeCache) { return this.nodeCache.get(id); } } applySpread(arg) { arg.spread = true; return arg; } sliceArgs(args, start, end) { start = start || 0; end = end || args.length; var filtered = [], newArgs = [], separator = ', ', spread, a, arg; for (a = start; a < end; a++) { arg = args[a]; if (!arg) { if (!spread) { filtered.push(arg); } continue; } if (arg.spread && arg.$isFashionList) { if (spread) { filtered.push(spread); } spread = arg; separator = spread.separator || separator; } else { filtered.push(arg); } } for (a = 0; a < filtered.length; a++) { arg = filtered[a]; separator = (arg && arg.splatSeparator) || separator; newArgs.push(filtered[a]); } if (spread) { newArgs.push.apply(newArgs, spread.items); } return new List(newArgs, separator); } applySpreadArgs(args, name) { var newArgs = [], hadSpread = false, offset = 0, arg, a, item, i, items, key, map, defaults, proc, param, paramName; proc = this.context && this.context.preprocessor; if (proc) { defaults = proc.mixinDeclarations[name]; if (defaults) { offset = 1; } else { defaults = proc.functionDeclarations[name] } defaults = defaults && defaults.parameters; } for (a = 0; a < args.length; a++) { arg = args[a]; if (arg && arg.spread && arg.$isFashionMap && defaults) { items = arg.items; map = {}; for (key in arg.map) { map['$' + Fashion.getJsName(key)] = arg.map[key]; } for (var p = 0; p < defaults.length; p++) { param = defaults[p]; paramName = Fashion.getJsName(param.name); if (paramName in map) { newArgs.push(items[map[paramName]]); delete map[paramName]; } else if (!param.varArgs) { newArgs.push(undefined); } } for (key in map) { item = items[map[key]]; newArgs.push(item); } hadSpread = true; } else if (arg && arg.spread && arg.$isFashionList) { items = arg.getItems(); for (i = 0; i < items.length; i++) { item = items[i]; item && (item.splatSeparator = arg.separator); newArgs.push(item); } hadSpread = true; } else if (arg || !hadSpread) { newArgs.push(arg); } // clear the flag indicating the spread argument // so subsequent calls using this same variable will not // be contaminated arg && (arg.spread = undefined); } var misisngParams = this.context && this.context.missingParameters; if (misisngParams && (misisngParams == 'error')) { if (defaults) { for (var d = 0; d < defaults.length; d++) { if (!defaults[d].hasOwnProperty('default') && !defaults[d].varArgs) { if (newArgs[d + offset] === undefined) { Fashion.raiseAt("No value supplied for argument : " + defaults[d].name, null, this.getCallStack()); } } } } } return newArgs; } warn(arg) { Fashion.warn(arg, this.getSourceInfo()); } error(arg) { Fashion.raiseAt(arg, null, this.getCallStack()); } debug() { Fashion.debug.apply(Fashion, arguments); } setCaches (transpiler) { this.docCache = transpiler.docCache; this.stringCache = transpiler.stringCache; this.nodeCache = transpiler.nodeCache; } copyRuntimeState (runtime) { this._dynamics = runtime._dynamics; this.registered = runtime.registered; this.functions = runtime.functions; this.mixins = runtime.mixins; } test (val) { val = this.unbox(val); if (val == null || val === false) { return false; } return true; } and (a, b) { if (this.test(a)) { return b; } return a; } or (a, b) { if (this.test(a)) { return a; } return b; } } Fashion.apply(Runtime.prototype, { box: Type.box, unbox: Type.unbox, Scope: Scope, isFashionRuntime: true, functions: null, code: null, fn: null, stringCache: null, docCache: null, types: Types, _globalScope: null, _currentScope: null, _dynamics: null, context: null, reserved: { 'if': true, 'else': true } }); module.exports = Runtime;