Created
October 9, 2018 10:12
-
-
Save GavinJoyce/649ae8f874c0bb2acab79759f07d243e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enifed('@glimmer/opcode-compiler', ['exports', '@ember/polyfills', 'ember-babel', '@glimmer/util', '@glimmer/vm', '@glimmer/wire-format', '@glimmer/encoder', '@glimmer/program'], function (exports, _polyfills, _emberBabel, _util, _vm, _wireFormat, _encoder, _program) { | |
'use strict'; | |
exports.PLACEHOLDER_HANDLE = exports.WrappedBuilder = exports.logOpcode = exports.debugSlice = exports.debug = exports.templateFactory = exports.PartialDefinition = exports.StdOpcodeBuilder = exports.OpcodeBuilder = exports.EagerOpcodeBuilder = exports.LazyOpcodeBuilder = exports.CompilableProgram = exports.CompilableBlock = exports.debugCompiler = exports.AbstractCompiler = exports.compile = exports.LazyCompiler = exports.Macros = exports.ATTRS_BLOCK = undefined; | |
var PLACEHOLDER_HANDLE = -1; | |
var Ops$1; | |
(function (Ops$$1) { | |
Ops$$1[Ops$$1["OpenComponentElement"] = 0] = "OpenComponentElement"; | |
Ops$$1[Ops$$1["DidCreateElement"] = 1] = "DidCreateElement"; | |
Ops$$1[Ops$$1["SetComponentAttrs"] = 2] = "SetComponentAttrs"; | |
Ops$$1[Ops$$1["DidRenderLayout"] = 3] = "DidRenderLayout"; | |
Ops$$1[Ops$$1["Debugger"] = 4] = "Debugger"; | |
})(Ops$1 || (Ops$1 = {})); | |
var Ops$2 = _wireFormat.Ops; | |
var ATTRS_BLOCK = '&attrs'; | |
var Compilers = function () { | |
function Compilers() { | |
var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; | |
(0, _emberBabel.classCallCheck)(this, Compilers); | |
this.offset = offset; | |
this.names = (0, _util.dict)(); | |
this.funcs = []; | |
} | |
Compilers.prototype.add = function add(name, func) { | |
this.funcs.push(func); | |
this.names[name] = this.funcs.length - 1; | |
}; | |
Compilers.prototype.compile = function compile(sexp, builder) { | |
var name = sexp[this.offset]; | |
var index = this.names[name]; | |
var func = this.funcs[index]; | |
func(sexp, builder); | |
}; | |
return Compilers; | |
}(); | |
var _statementCompiler = void 0; | |
function statementCompiler() { | |
if (_statementCompiler) { | |
return _statementCompiler; | |
} | |
var STATEMENTS = _statementCompiler = new Compilers(); | |
STATEMENTS.add(Ops$2.Text, function (sexp, builder) { | |
builder.text(sexp[1]); | |
}); | |
STATEMENTS.add(Ops$2.Comment, function (sexp, builder) { | |
builder.comment(sexp[1]); | |
}); | |
STATEMENTS.add(Ops$2.CloseElement, function (_sexp, builder) { | |
builder.closeElement(); | |
}); | |
STATEMENTS.add(Ops$2.FlushElement, function (_sexp, builder) { | |
builder.flushElement(); | |
}); | |
STATEMENTS.add(Ops$2.Modifier, function (sexp, builder) { | |
var referrer = builder.referrer; | |
var name = sexp[1], | |
params = sexp[2], | |
hash = sexp[3]; | |
var handle = builder.compiler.resolveModifier(name, referrer); | |
if (handle !== null) { | |
builder.modifier(handle, params, hash); | |
} else { | |
throw new Error('Compile Error ' + name + ' is not a modifier: Helpers may not be used in the element form.'); | |
} | |
}); | |
STATEMENTS.add(Ops$2.StaticAttr, function (sexp, builder) { | |
var name = sexp[1], | |
value = sexp[2], | |
namespace = sexp[3]; | |
builder.staticAttr(name, namespace, value); | |
}); | |
STATEMENTS.add(Ops$2.DynamicAttr, function (sexp, builder) { | |
dynamicAttr(sexp, false, builder); | |
}); | |
STATEMENTS.add(Ops$2.TrustingAttr, function (sexp, builder) { | |
dynamicAttr(sexp, true, builder); | |
}); | |
STATEMENTS.add(Ops$2.OpenElement, function (sexp, builder) { | |
builder.openPrimitiveElement(sexp[1]); | |
}); | |
STATEMENTS.add(Ops$2.OpenSplattedElement, function (sexp, builder) { | |
builder.setComponentAttrs(true); | |
builder.putComponentOperations(); | |
builder.openPrimitiveElement(sexp[1]); | |
}); | |
STATEMENTS.add(Ops$2.DynamicComponent, function (sexp, builder) { | |
var definition = sexp[1], | |
attrs = sexp[2], | |
args = sexp[3], | |
template = sexp[4]; | |
var block = builder.template(template); | |
var attrsBlock = null; | |
if (attrs.length > 0) { | |
var wrappedAttrs = [[Ops$2.ClientSideStatement, Ops$1.SetComponentAttrs, true]].concat(attrs, [[Ops$2.ClientSideStatement, Ops$1.SetComponentAttrs, false]]); | |
attrsBlock = builder.inlineBlock({ statements: wrappedAttrs, parameters: _util.EMPTY_ARRAY }); | |
} | |
builder.dynamicComponent(definition, attrsBlock, null, args, false, block, null); | |
}); | |
STATEMENTS.add(Ops$2.Component, function (sexp, builder) { | |
var tag = sexp[1], | |
_attrs = sexp[2], | |
args = sexp[3], | |
block = sexp[4]; | |
var referrer = builder.referrer; | |
var _builder$compiler$res = builder.compiler.resolveLayoutForTag(tag, referrer), | |
handle = _builder$compiler$res.handle, | |
capabilities = _builder$compiler$res.capabilities, | |
compilable = _builder$compiler$res.compilable; | |
if (handle !== null && capabilities !== null) { | |
var attrs = [[Ops$2.ClientSideStatement, Ops$1.SetComponentAttrs, true]].concat(_attrs, [[Ops$2.ClientSideStatement, Ops$1.SetComponentAttrs, false]]); | |
var attrsBlock = builder.inlineBlock({ statements: attrs, parameters: _util.EMPTY_ARRAY }); | |
var child = builder.template(block); | |
if (compilable) { | |
builder.pushComponentDefinition(handle); | |
builder.invokeStaticComponent(capabilities, compilable, attrsBlock, null, args, false, child && child); | |
} else { | |
builder.pushComponentDefinition(handle); | |
builder.invokeComponent(capabilities, attrsBlock, null, args, false, child && child); | |
} | |
} else { | |
throw new Error('Compile Error: Cannot find component ' + tag); | |
} | |
}); | |
STATEMENTS.add(Ops$2.Partial, function (sexp, builder) { | |
var name = sexp[1], | |
evalInfo = sexp[2]; | |
var referrer = builder.referrer; | |
builder.replayableIf({ | |
args: function () { | |
builder.expr(name); | |
builder.dup(); | |
return 2; | |
}, | |
ifTrue: function () { | |
builder.invokePartial(referrer, builder.evalSymbols(), evalInfo); | |
builder.popScope(); | |
builder.popFrame(); // FIXME: WAT | |
} | |
}); | |
}); | |
STATEMENTS.add(Ops$2.Yield, function (sexp, builder) { | |
var to = sexp[1], | |
params = sexp[2]; | |
builder.yield(to, params); | |
}); | |
STATEMENTS.add(Ops$2.AttrSplat, function (sexp, builder) { | |
var to = sexp[1]; | |
builder.yield(to, []); | |
builder.setComponentAttrs(false); | |
}); | |
STATEMENTS.add(Ops$2.Debugger, function (sexp, builder) { | |
var evalInfo = sexp[1]; | |
builder.debugger(builder.evalSymbols(), evalInfo); | |
}); | |
STATEMENTS.add(Ops$2.ClientSideStatement, function (sexp, builder) { | |
CLIENT_SIDE.compile(sexp, builder); | |
}); | |
STATEMENTS.add(Ops$2.Append, function (sexp, builder) { | |
var value = sexp[1], | |
trusting = sexp[2]; | |
var returned = builder.compileInline(sexp) || value; | |
if (returned === true) return; | |
builder.guardedAppend(value, trusting); | |
}); | |
STATEMENTS.add(Ops$2.Block, function (sexp, builder) { | |
var name = sexp[1], | |
params = sexp[2], | |
hash = sexp[3], | |
_template = sexp[4], | |
_inverse = sexp[5]; | |
var template = builder.template(_template); | |
var inverse = builder.template(_inverse); | |
var templateBlock = template && template; | |
var inverseBlock = inverse && inverse; | |
builder.compileBlock(name, params, hash, templateBlock, inverseBlock); | |
}); | |
var CLIENT_SIDE = new Compilers(1); | |
CLIENT_SIDE.add(Ops$1.OpenComponentElement, function (sexp, builder) { | |
builder.putComponentOperations(); | |
builder.openPrimitiveElement(sexp[2]); | |
}); | |
CLIENT_SIDE.add(Ops$1.DidCreateElement, function (_sexp, builder) { | |
builder.didCreateElement(_vm.Register.s0); | |
}); | |
CLIENT_SIDE.add(Ops$1.SetComponentAttrs, function (sexp, builder) { | |
builder.setComponentAttrs(sexp[2]); | |
}); | |
CLIENT_SIDE.add(Ops$1.Debugger, function () { | |
// tslint:disable-next-line:no-debugger | |
debugger; | |
}); | |
CLIENT_SIDE.add(Ops$1.DidRenderLayout, function (_sexp, builder) { | |
builder.didRenderLayout(_vm.Register.s0); | |
}); | |
return STATEMENTS; | |
} | |
function dynamicAttr(sexp, trusting, builder) { | |
var name = sexp[1], | |
value = sexp[2], | |
namespace = sexp[3]; | |
builder.expr(value); | |
if (namespace) { | |
builder.dynamicAttr(name, namespace, trusting); | |
} else { | |
builder.dynamicAttr(name, null, trusting); | |
} | |
} | |
var _expressionCompiler = void 0; | |
function expressionCompiler() { | |
if (_expressionCompiler) { | |
return _expressionCompiler; | |
} | |
var EXPRESSIONS = _expressionCompiler = new Compilers(); | |
EXPRESSIONS.add(Ops$2.Unknown, function (sexp, builder) { | |
var compiler = builder.compiler, | |
referrer = builder.referrer, | |
asPartial = builder.containingLayout.asPartial; | |
var name = sexp[1]; | |
var handle = compiler.resolveHelper(name, referrer); | |
if (handle !== null) { | |
builder.helper(handle, null, null); | |
} else if (asPartial) { | |
builder.resolveMaybeLocal(name); | |
} else { | |
builder.getVariable(0); | |
builder.getProperty(name); | |
} | |
}); | |
EXPRESSIONS.add(Ops$2.Concat, function (sexp, builder) { | |
var parts = sexp[1]; | |
for (var i = 0; i < parts.length; i++) { | |
builder.expr(parts[i]); | |
} | |
builder.concat(parts.length); | |
}); | |
EXPRESSIONS.add(Ops$2.Helper, function (sexp, builder) { | |
var compiler = builder.compiler, | |
referrer = builder.referrer; | |
var name = sexp[1], | |
params = sexp[2], | |
hash = sexp[3]; | |
// TODO: triage this in the WF compiler | |
if (name === 'component') { | |
var definition = params[0], | |
restArgs = params.slice(1); | |
builder.curryComponent(definition, restArgs, hash, true); | |
return; | |
} | |
var handle = compiler.resolveHelper(name, referrer); | |
if (handle !== null) { | |
builder.helper(handle, params, hash); | |
} else { | |
throw new Error('Compile Error: ' + name + ' is not a helper'); | |
} | |
}); | |
EXPRESSIONS.add(Ops$2.Get, function (sexp, builder) { | |
var head = sexp[1], | |
path = sexp[2]; | |
builder.getVariable(head); | |
for (var i = 0; i < path.length; i++) { | |
builder.getProperty(path[i]); | |
} | |
}); | |
EXPRESSIONS.add(Ops$2.MaybeLocal, function (sexp, builder) { | |
var path = sexp[1]; | |
if (builder.containingLayout.asPartial) { | |
var head = path[0]; | |
path = path.slice(1); | |
builder.resolveMaybeLocal(head); | |
} else { | |
builder.getVariable(0); | |
} | |
for (var i = 0; i < path.length; i++) { | |
builder.getProperty(path[i]); | |
} | |
}); | |
EXPRESSIONS.add(Ops$2.Undefined, function (_sexp, builder) { | |
return builder.pushPrimitiveReference(undefined); | |
}); | |
EXPRESSIONS.add(Ops$2.HasBlock, function (sexp, builder) { | |
builder.hasBlock(sexp[1]); | |
}); | |
EXPRESSIONS.add(Ops$2.HasBlockParams, function (sexp, builder) { | |
builder.hasBlockParams(sexp[1]); | |
}); | |
return EXPRESSIONS; | |
} | |
var Macros = function Macros() { | |
(0, _emberBabel.classCallCheck)(this, Macros); | |
var _populateBuiltins = populateBuiltins(), | |
blocks = _populateBuiltins.blocks, | |
inlines = _populateBuiltins.inlines; | |
this.blocks = blocks; | |
this.inlines = inlines; | |
}; | |
var Blocks = function () { | |
function Blocks() { | |
(0, _emberBabel.classCallCheck)(this, Blocks); | |
this.names = (0, _util.dict)(); | |
this.funcs = []; | |
} | |
Blocks.prototype.add = function add(name, func) { | |
this.funcs.push(func); | |
this.names[name] = this.funcs.length - 1; | |
}; | |
Blocks.prototype.addMissing = function addMissing(func) { | |
this.missing = func; | |
}; | |
Blocks.prototype.compile = function compile(name, params, hash, template, inverse, builder) { | |
var index = this.names[name]; | |
if (index === undefined) { | |
var func = this.missing; | |
var handled = func(name, params, hash, template, inverse, builder); | |
} else { | |
var _func = this.funcs[index]; | |
_func(params, hash, template, inverse, builder); | |
} | |
}; | |
return Blocks; | |
}(); | |
var Inlines = function () { | |
function Inlines() { | |
(0, _emberBabel.classCallCheck)(this, Inlines); | |
this.names = (0, _util.dict)(); | |
this.funcs = []; | |
} | |
Inlines.prototype.add = function add(name, func) { | |
this.funcs.push(func); | |
this.names[name] = this.funcs.length - 1; | |
}; | |
Inlines.prototype.addMissing = function addMissing(func) { | |
this.missing = func; | |
}; | |
Inlines.prototype.compile = function compile(sexp, builder) { | |
var value = sexp[1]; | |
// TODO: Fix this so that expression macros can return | |
// things like components, so that {{component foo}} | |
// is the same as {{(component foo)}} | |
if (!Array.isArray(value)) return ['expr', value]; | |
var name = void 0; | |
var params = void 0; | |
var hash = void 0; | |
if (value[0] === Ops$2.Helper) { | |
name = value[1]; | |
params = value[2]; | |
hash = value[3]; | |
} else if (value[0] === Ops$2.Unknown) { | |
name = value[1]; | |
params = hash = null; | |
} else { | |
return ['expr', value]; | |
} | |
var index = this.names[name]; | |
if (index === undefined && this.missing) { | |
var func = this.missing; | |
var returned = func(name, params, hash, builder); | |
return returned === false ? ['expr', value] : returned; | |
} else if (index !== undefined) { | |
var _func2 = this.funcs[index]; | |
var _returned = _func2(name, params, hash, builder); | |
return _returned === false ? ['expr', value] : _returned; | |
} else { | |
return ['expr', value]; | |
} | |
}; | |
return Inlines; | |
}(); | |
function populateBuiltins() { | |
var blocks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Blocks(); | |
var inlines = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Inlines(); | |
blocks.add('if', function (params, _hash, template, inverse, builder) { | |
// PutArgs | |
// Test(Environment) | |
// Enter(BEGIN, END) | |
// BEGIN: Noop | |
// JumpUnless(ELSE) | |
// Evaluate(default) | |
// Jump(END) | |
// ELSE: Noop | |
// Evalulate(inverse) | |
// END: Noop | |
// Exit | |
if (!params || params.length !== 1) { | |
throw new Error('SYNTAX ERROR: #if requires a single argument'); | |
} | |
builder.replayableIf({ | |
args: function () { | |
builder.expr(params[0]); | |
builder.toBoolean(); | |
return 1; | |
}, | |
ifTrue: function () { | |
builder.invokeStaticBlock(template); | |
}, | |
ifFalse: function () { | |
if (inverse) { | |
builder.invokeStaticBlock(inverse); | |
} | |
} | |
}); | |
}); | |
blocks.add('unless', function (params, _hash, template, inverse, builder) { | |
// PutArgs | |
// Test(Environment) | |
// Enter(BEGIN, END) | |
// BEGIN: Noop | |
// JumpUnless(ELSE) | |
// Evaluate(default) | |
// Jump(END) | |
// ELSE: Noop | |
// Evalulate(inverse) | |
// END: Noop | |
// Exit | |
if (!params || params.length !== 1) { | |
throw new Error('SYNTAX ERROR: #unless requires a single argument'); | |
} | |
builder.replayableIf({ | |
args: function () { | |
builder.expr(params[0]); | |
builder.toBoolean(); | |
return 1; | |
}, | |
ifTrue: function () { | |
if (inverse) { | |
builder.invokeStaticBlock(inverse); | |
} | |
}, | |
ifFalse: function () { | |
builder.invokeStaticBlock(template); | |
} | |
}); | |
}); | |
blocks.add('with', function (params, _hash, template, inverse, builder) { | |
// PutArgs | |
// Test(Environment) | |
// Enter(BEGIN, END) | |
// BEGIN: Noop | |
// JumpUnless(ELSE) | |
// Evaluate(default) | |
// Jump(END) | |
// ELSE: Noop | |
// Evalulate(inverse) | |
// END: Noop | |
// Exit | |
if (!params || params.length !== 1) { | |
throw new Error('SYNTAX ERROR: #with requires a single argument'); | |
} | |
builder.replayableIf({ | |
args: function () { | |
builder.expr(params[0]); | |
builder.dup(); | |
builder.toBoolean(); | |
return 2; | |
}, | |
ifTrue: function () { | |
builder.invokeStaticBlock(template, 1); | |
}, | |
ifFalse: function () { | |
if (inverse) { | |
builder.invokeStaticBlock(inverse); | |
} | |
} | |
}); | |
}); | |
blocks.add('each', function (params, hash, template, inverse, builder) { | |
// Enter(BEGIN, END) | |
// BEGIN: Noop | |
// PutArgs | |
// PutIterable | |
// JumpUnless(ELSE) | |
// EnterList(BEGIN2, END2) | |
// ITER: Noop | |
// NextIter(BREAK) | |
// BEGIN2: Noop | |
// PushChildScope | |
// Evaluate(default) | |
// PopScope | |
// END2: Noop | |
// Exit | |
// Jump(ITER) | |
// BREAK: Noop | |
// ExitList | |
// Jump(END) | |
// ELSE: Noop | |
// Evalulate(inverse) | |
// END: Noop | |
// Exit | |
builder.replayable({ | |
args: function () { | |
if (hash && hash[0][0] === 'key') { | |
builder.expr(hash[1][0]); | |
} else { | |
builder.pushPrimitiveReference(null); | |
} | |
builder.expr(params[0]); | |
return 2; | |
}, | |
body: function () { | |
builder.putIterator(); | |
builder.jumpUnless('ELSE'); | |
builder.pushFrame(); | |
builder.dup(_vm.Register.fp, 1); | |
builder.returnTo('ITER'); | |
builder.enterList('BODY'); | |
builder.label('ITER'); | |
builder.iterate('BREAK'); | |
builder.label('BODY'); | |
builder.invokeStaticBlock(template, 2); | |
builder.pop(2); | |
builder.jump('FINALLY'); | |
builder.label('BREAK'); | |
builder.exitList(); | |
builder.popFrame(); | |
builder.jump('FINALLY'); | |
builder.label('ELSE'); | |
if (inverse) { | |
builder.invokeStaticBlock(inverse); | |
} | |
} | |
}); | |
}); | |
blocks.add('in-element', function (params, hash, template, _inverse, builder) { | |
if (!params || params.length !== 1) { | |
throw new Error('SYNTAX ERROR: #in-element requires a single argument'); | |
} | |
builder.replayableIf({ | |
args: function () { | |
var keys = hash[0], | |
values = hash[1]; | |
for (var i = 0; i < keys.length; i++) { | |
var key = keys[i]; | |
if (key === 'nextSibling' || key === 'guid') { | |
builder.expr(values[i]); | |
} else { | |
throw new Error('SYNTAX ERROR: #in-element does not take a `' + keys[0] + '` option'); | |
} | |
} | |
builder.expr(params[0]); | |
builder.dup(); | |
return 4; | |
}, | |
ifTrue: function () { | |
builder.pushRemoteElement(); | |
builder.invokeStaticBlock(template); | |
builder.popRemoteElement(); | |
} | |
}); | |
}); | |
blocks.add('-with-dynamic-vars', function (_params, hash, template, _inverse, builder) { | |
if (hash) { | |
var names = hash[0], | |
expressions = hash[1]; | |
builder.compileParams(expressions); | |
builder.pushDynamicScope(); | |
builder.bindDynamicScope(names); | |
builder.invokeStaticBlock(template); | |
builder.popDynamicScope(); | |
} else { | |
builder.invokeStaticBlock(template); | |
} | |
}); | |
blocks.add('component', function (_params, hash, template, inverse, builder) { | |
var tag = _params[0]; | |
if (typeof tag === 'string') { | |
var returned = builder.staticComponentHelper(_params[0], hash, template); | |
if (returned) return; | |
} | |
var definition = _params[0], | |
params = _params.slice(1); | |
builder.dynamicComponent(definition, null, params, hash, true, template, inverse); | |
}); | |
inlines.add('component', function (_name, _params, hash, builder) { | |
var tag = _params && _params[0]; | |
if (typeof tag === 'string') { | |
var returned = builder.staticComponentHelper(tag, hash, null); | |
if (returned) return true; | |
} | |
var definition = _params[0], | |
params = _params.slice(1); | |
builder.dynamicComponent(definition, null, params, hash, true, null, null); | |
return true; | |
}); | |
return { blocks: blocks, inlines: inlines }; | |
} | |
var PLACEHOLDER_HANDLE$1 = -1; | |
var CompilableProgram = function () { | |
function CompilableProgram(compiler, layout) { | |
(0, _emberBabel.classCallCheck)(this, CompilableProgram); | |
this.compiler = compiler; | |
this.layout = layout; | |
this.compiled = null; | |
} | |
CompilableProgram.prototype.compile = function compile() { | |
if (this.compiled !== null) return this.compiled; | |
this.compiled = PLACEHOLDER_HANDLE$1; | |
var statements = this.layout.block.statements; | |
return this.compiled = this.compiler.add(statements, this.layout); | |
}; | |
(0, _emberBabel.createClass)(CompilableProgram, [{ | |
key: 'symbolTable', | |
get: function () { | |
return this.layout.block; | |
} | |
}]); | |
return CompilableProgram; | |
}(); | |
var CompilableBlock = function () { | |
function CompilableBlock(compiler, parsed) { | |
(0, _emberBabel.classCallCheck)(this, CompilableBlock); | |
this.compiler = compiler; | |
this.parsed = parsed; | |
this.compiled = null; | |
} | |
CompilableBlock.prototype.compile = function compile() { | |
if (this.compiled !== null) return this.compiled; | |
// Track that compilation has started but not yet finished by temporarily | |
// using a placeholder handle. In eager compilation mode, where compile() | |
// may be called recursively, we use this as a signal that the handle cannot | |
// be known synchronously and must be linked lazily. | |
this.compiled = PLACEHOLDER_HANDLE$1; | |
var _parsed = this.parsed, | |
statements = _parsed.block.statements, | |
containingLayout = _parsed.containingLayout; | |
return this.compiled = this.compiler.add(statements, containingLayout); | |
}; | |
(0, _emberBabel.createClass)(CompilableBlock, [{ | |
key: 'symbolTable', | |
get: function () { | |
return this.parsed.block; | |
} | |
}]); | |
return CompilableBlock; | |
}(); | |
function compile(statements, builder, compiler) { | |
var sCompiler = statementCompiler(); | |
for (var i = 0; i < statements.length; i++) { | |
sCompiler.compile(statements[i], builder); | |
} | |
var handle = builder.commit(); | |
return handle; | |
} | |
function debugSlice(program, start, end) {} | |
function logOpcode(type, params) { | |
var out = type; | |
if (params) { | |
var args = Object.keys(params).map(function (p) { | |
return ' ' + p + '=' + json(params[p]); | |
}).join(''); | |
out += args; | |
} | |
return '(' + out + ')'; | |
} | |
function json(param) {} | |
function debug(pos, c, op) { | |
for (var _len = arguments.length, operands = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) { | |
operands[_key - 3] = arguments[_key]; | |
} | |
var metadata = null; | |
if (!metadata) { | |
throw (0, _util.unreachable)('Missing Opcode Metadata for ' + op); | |
} | |
var out = (0, _util.dict)(); | |
metadata.ops.forEach(function (operand, index) { | |
var op = operands[index]; | |
switch (operand.type) { | |
case 'to': | |
out[operand.name] = pos + op; | |
break; | |
case 'i32': | |
case 'symbol': | |
case 'block': | |
out[operand.name] = op; | |
break; | |
case 'handle': | |
out[operand.name] = c.resolveHandle(op); | |
break; | |
case 'str': | |
out[operand.name] = c.getString(op); | |
break; | |
case 'option-str': | |
out[operand.name] = op ? c.getString(op) : null; | |
break; | |
case 'str-array': | |
out[operand.name] = c.getStringArray(op); | |
break; | |
case 'array': | |
out[operand.name] = c.getArray(op); | |
break; | |
case 'bool': | |
out[operand.name] = !!op; | |
break; | |
case 'primitive': | |
out[operand.name] = decodePrimitive(op, c); | |
break; | |
case 'register': | |
out[operand.name] = _vm.Register[op]; | |
break; | |
case 'serializable': | |
out[operand.name] = c.getSerializable(op); | |
break; | |
case 'lazy-constant': | |
out[operand.name] = c.getOther(op); | |
break; | |
} | |
}); | |
return [metadata.name, out]; | |
} | |
function decodePrimitive(primitive, constants) { | |
var flag = primitive & 7; // 111 | |
var value = primitive >> 3; | |
switch (flag) { | |
case 0 /* NUMBER */: | |
return value; | |
case 1 /* FLOAT */: | |
return constants.getNumber(value); | |
case 2 /* STRING */: | |
return constants.getString(value); | |
case 3 /* BOOLEAN_OR_VOID */: | |
switch (value) { | |
case 0: | |
return false; | |
case 1: | |
return true; | |
case 2: | |
return null; | |
case 3: | |
return undefined; | |
} | |
case 4 /* NEGATIVE */: | |
return constants.getNumber(value); | |
default: | |
throw (0, _util.unreachable)(); | |
} | |
} | |
var StdLib = function () { | |
function StdLib(main, trustingGuardedAppend, cautiousGuardedAppend) { | |
(0, _emberBabel.classCallCheck)(this, StdLib); | |
this.main = main; | |
this.trustingGuardedAppend = trustingGuardedAppend; | |
this.cautiousGuardedAppend = cautiousGuardedAppend; | |
} | |
StdLib.compile = function compile(compiler) { | |
var main = this.std(compiler, function (b) { | |
return b.main(); | |
}); | |
var trustingGuardedAppend = this.std(compiler, function (b) { | |
return b.stdAppend(true); | |
}); | |
var cautiousGuardedAppend = this.std(compiler, function (b) { | |
return b.stdAppend(false); | |
}); | |
return new StdLib(main, trustingGuardedAppend, cautiousGuardedAppend); | |
}; | |
StdLib.std = function std(compiler, callback) { | |
return StdOpcodeBuilder.build(compiler, callback); | |
}; | |
StdLib.prototype.getAppend = function getAppend(trusting) { | |
return trusting ? this.trustingGuardedAppend : this.cautiousGuardedAppend; | |
}; | |
return StdLib; | |
}(); | |
var AbstractCompiler = function () { | |
function AbstractCompiler(macros, program, resolver) { | |
(0, _emberBabel.classCallCheck)(this, AbstractCompiler); | |
this.macros = macros; | |
this.program = program; | |
this.resolver = resolver; | |
this.initialize(); | |
} | |
AbstractCompiler.prototype.initialize = function initialize() { | |
this.stdLib = StdLib.compile(this); | |
}; | |
AbstractCompiler.prototype.compileInline = function compileInline(sexp, builder) { | |
var inlines = this.macros.inlines; | |
return inlines.compile(sexp, builder); | |
}; | |
AbstractCompiler.prototype.compileBlock = function compileBlock(name, params, hash, template, inverse, builder) { | |
var blocks = this.macros.blocks; | |
blocks.compile(name, params, hash, template, inverse, builder); | |
}; | |
AbstractCompiler.prototype.add = function add(statements, containingLayout) { | |
return compile(statements, this.builderFor(containingLayout), this); | |
}; | |
AbstractCompiler.prototype.commit = function commit(scopeSize, buffer) { | |
var heap = this.program.heap; | |
// TODO: change the whole malloc API and do something more efficient | |
var handle = heap.malloc(); | |
for (var i = 0; i < buffer.length; i++) { | |
var value = buffer[i]; | |
if (typeof value === 'function') { | |
heap.pushPlaceholder(value); | |
} else { | |
heap.push(value); | |
} | |
} | |
heap.finishMalloc(handle, scopeSize); | |
return handle; | |
}; | |
AbstractCompiler.prototype.resolveLayoutForTag = function resolveLayoutForTag(tag, referrer) { | |
var resolver = this.resolver; | |
var handle = resolver.lookupComponentDefinition(tag, referrer); | |
if (handle === null) return { handle: null, capabilities: null, compilable: null }; | |
return this.resolveLayoutForHandle(handle); | |
}; | |
AbstractCompiler.prototype.resolveLayoutForHandle = function resolveLayoutForHandle(handle) { | |
var resolver = this.resolver; | |
var capabilities = resolver.getCapabilities(handle); | |
var compilable = null; | |
if (!capabilities.dynamicLayout) { | |
compilable = resolver.getLayout(handle); | |
} | |
return { | |
handle: handle, | |
capabilities: capabilities, | |
compilable: compilable | |
}; | |
}; | |
AbstractCompiler.prototype.resolveModifier = function resolveModifier(name, referrer) { | |
return this.resolver.lookupModifier(name, referrer); | |
}; | |
AbstractCompiler.prototype.resolveHelper = function resolveHelper(name, referrer) { | |
return this.resolver.lookupHelper(name, referrer); | |
}; | |
(0, _emberBabel.createClass)(AbstractCompiler, [{ | |
key: 'constants', | |
get: function () { | |
return this.program.constants; | |
} | |
}]); | |
return AbstractCompiler; | |
}(); | |
var debugCompiler = void 0; | |
var WrappedBuilder = function () { | |
function WrappedBuilder(compiler, layout) { | |
(0, _emberBabel.classCallCheck)(this, WrappedBuilder); | |
this.compiler = compiler; | |
this.layout = layout; | |
this.compiled = null; | |
var block = layout.block; | |
var symbols = block.symbols.slice(); | |
// ensure ATTRS_BLOCK is always included (only once) in the list of symbols | |
var attrsBlockIndex = symbols.indexOf(ATTRS_BLOCK); | |
if (attrsBlockIndex === -1) { | |
this.attrsBlockNumber = symbols.push(ATTRS_BLOCK); | |
} else { | |
this.attrsBlockNumber = attrsBlockIndex + 1; | |
} | |
this.symbolTable = { | |
hasEval: block.hasEval, | |
symbols: symbols | |
}; | |
} | |
WrappedBuilder.prototype.compile = function compile() { | |
if (this.compiled !== null) return this.compiled; | |
//========DYNAMIC | |
// PutValue(TagExpr) | |
// Test | |
// JumpUnless(BODY) | |
// PutComponentOperations | |
// OpenDynamicPrimitiveElement | |
// DidCreateElement | |
// ...attr statements... | |
// FlushElement | |
// BODY: Noop | |
// ...body statements... | |
// PutValue(TagExpr) | |
// Test | |
// JumpUnless(END) | |
// CloseElement | |
// END: Noop | |
// DidRenderLayout | |
// Exit | |
// | |
//========STATIC | |
// OpenPrimitiveElementOpcode | |
// DidCreateElement | |
// ...attr statements... | |
// FlushElement | |
// ...body statements... | |
// CloseElement | |
// DidRenderLayout | |
// Exit | |
var compiler = this.compiler, | |
layout = this.layout; | |
var b = compiler.builderFor(layout); | |
b.startLabels(); | |
b.fetch(_vm.Register.s1); | |
b.getComponentTagName(_vm.Register.s0); | |
b.primitiveReference(); | |
b.dup(); | |
b.load(_vm.Register.s1); | |
b.jumpUnless('BODY'); | |
b.fetch(_vm.Register.s1); | |
b.setComponentAttrs(true); | |
b.putComponentOperations(); | |
b.openDynamicElement(); | |
b.didCreateElement(_vm.Register.s0); | |
b.yield(this.attrsBlockNumber, []); | |
b.setComponentAttrs(false); | |
b.flushElement(); | |
b.label('BODY'); | |
b.invokeStaticBlock(blockFor(layout, compiler)); | |
b.fetch(_vm.Register.s1); | |
b.jumpUnless('END'); | |
b.closeElement(); | |
b.label('END'); | |
b.load(_vm.Register.s1); | |
b.stopLabels(); | |
var handle = b.commit(); | |
return this.compiled = handle; | |
}; | |
return WrappedBuilder; | |
}(); | |
function blockFor(layout, compiler) { | |
return new CompilableBlock(compiler, { | |
block: { | |
statements: layout.block.statements, | |
parameters: _util.EMPTY_ARRAY | |
}, | |
containingLayout: layout | |
}); | |
} | |
var ComponentBuilder = function () { | |
function ComponentBuilder(builder) { | |
(0, _emberBabel.classCallCheck)(this, ComponentBuilder); | |
this.builder = builder; | |
} | |
ComponentBuilder.prototype.static = function _static(handle, args) { | |
var params = args[0], | |
hash = args[1], | |
_default = args[2], | |
inverse = args[3]; | |
var builder = this.builder; | |
if (handle !== null) { | |
var _builder$compiler$res2 = builder.compiler.resolveLayoutForHandle(handle), | |
capabilities = _builder$compiler$res2.capabilities, | |
compilable = _builder$compiler$res2.compilable; | |
if (compilable) { | |
builder.pushComponentDefinition(handle); | |
builder.invokeStaticComponent(capabilities, compilable, null, params, hash, false, _default, inverse); | |
} else { | |
builder.pushComponentDefinition(handle); | |
builder.invokeComponent(capabilities, null, params, hash, false, _default, inverse); | |
} | |
} | |
}; | |
return ComponentBuilder; | |
}(); | |
var Labels = function () { | |
function Labels() { | |
(0, _emberBabel.classCallCheck)(this, Labels); | |
this.labels = (0, _util.dict)(); | |
this.targets = []; | |
} | |
Labels.prototype.label = function label(name, index) { | |
this.labels[name] = index; | |
}; | |
Labels.prototype.target = function target(at, _target) { | |
this.targets.push({ at: at, target: _target }); | |
}; | |
Labels.prototype.patch = function patch(encoder) { | |
var targets = this.targets, | |
labels = this.labels; | |
for (var i = 0; i < targets.length; i++) { | |
var _targets$i = targets[i], | |
at = _targets$i.at, | |
target = _targets$i.target; | |
var address = labels[target] - at; | |
encoder.patch(at, address); | |
} | |
}; | |
return Labels; | |
}(); | |
var StdOpcodeBuilder = function () { | |
function StdOpcodeBuilder(compiler) { | |
var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | |
(0, _emberBabel.classCallCheck)(this, StdOpcodeBuilder); | |
this.size = size; | |
this.encoder = new _encoder.InstructionEncoder([]); | |
this.labelsStack = new _util.Stack(); | |
this.compiler = compiler; | |
} | |
StdOpcodeBuilder.build = function build(compiler, callback) { | |
var builder = new StdOpcodeBuilder(compiler); | |
callback(builder); | |
return builder.commit(); | |
}; | |
StdOpcodeBuilder.prototype.push = function push(name) { | |
switch (arguments.length) { | |
case 1: | |
return this.encoder.encode(name, 0); | |
case 2: | |
return this.encoder.encode(name, 0, arguments[1]); | |
case 3: | |
return this.encoder.encode(name, 0, arguments[1], arguments[2]); | |
default: | |
return this.encoder.encode(name, 0, arguments[1], arguments[2], arguments[3]); | |
} | |
}; | |
StdOpcodeBuilder.prototype.pushMachine = function pushMachine(name) { | |
switch (arguments.length) { | |
case 1: | |
return this.encoder.encode(name, 1024 /* MACHINE_MASK */); | |
case 2: | |
return this.encoder.encode(name, 1024 /* MACHINE_MASK */, arguments[1]); | |
case 3: | |
return this.encoder.encode(name, 1024 /* MACHINE_MASK */, arguments[1], arguments[2]); | |
default: | |
return this.encoder.encode(name, 1024 /* MACHINE_MASK */, arguments[1], arguments[2], arguments[3]); | |
} | |
}; | |
StdOpcodeBuilder.prototype.commit = function commit() { | |
this.pushMachine(24 /* Return */); | |
return this.compiler.commit(this.size, this.encoder.buffer); | |
}; | |
StdOpcodeBuilder.prototype.reserve = function reserve(name) { | |
this.encoder.encode(name, 0, -1); | |
}; | |
StdOpcodeBuilder.prototype.reserveWithOperand = function reserveWithOperand(name, operand) { | |
this.encoder.encode(name, 0, -1, operand); | |
}; | |
StdOpcodeBuilder.prototype.reserveMachine = function reserveMachine(name) { | |
this.encoder.encode(name, 1024 /* MACHINE_MASK */, -1); | |
}; | |
StdOpcodeBuilder.prototype.main = function main() { | |
this.push(68 /* Main */, _vm.Register.s0); | |
this.invokePreparedComponent(false, false, true); | |
}; | |
StdOpcodeBuilder.prototype.appendHTML = function appendHTML() { | |
this.push(28 /* AppendHTML */); | |
}; | |
StdOpcodeBuilder.prototype.appendSafeHTML = function appendSafeHTML() { | |
this.push(29 /* AppendSafeHTML */); | |
}; | |
StdOpcodeBuilder.prototype.appendDocumentFragment = function appendDocumentFragment() { | |
this.push(30 /* AppendDocumentFragment */); | |
}; | |
StdOpcodeBuilder.prototype.appendNode = function appendNode() { | |
this.push(31 /* AppendNode */); | |
}; | |
StdOpcodeBuilder.prototype.appendText = function appendText() { | |
this.push(32 /* AppendText */); | |
}; | |
StdOpcodeBuilder.prototype.beginComponentTransaction = function beginComponentTransaction() { | |
this.push(91 /* BeginComponentTransaction */); | |
}; | |
StdOpcodeBuilder.prototype.commitComponentTransaction = function commitComponentTransaction() { | |
this.push(92 /* CommitComponentTransaction */); | |
}; | |
StdOpcodeBuilder.prototype.pushDynamicScope = function pushDynamicScope() { | |
this.push(44 /* PushDynamicScope */); | |
}; | |
StdOpcodeBuilder.prototype.popDynamicScope = function popDynamicScope() { | |
this.push(45 /* PopDynamicScope */); | |
}; | |
StdOpcodeBuilder.prototype.pushRemoteElement = function pushRemoteElement() { | |
this.push(41 /* PushRemoteElement */); | |
}; | |
StdOpcodeBuilder.prototype.popRemoteElement = function popRemoteElement() { | |
this.push(42 /* PopRemoteElement */); | |
}; | |
StdOpcodeBuilder.prototype.pushRootScope = function pushRootScope(symbols, bindCallerScope) { | |
this.push(20 /* RootScope */, symbols, bindCallerScope ? 1 : 0); | |
}; | |
StdOpcodeBuilder.prototype.pushVirtualRootScope = function pushVirtualRootScope(register) { | |
this.push(21 /* VirtualRootScope */, register); | |
}; | |
StdOpcodeBuilder.prototype.pushChildScope = function pushChildScope() { | |
this.push(22 /* ChildScope */); | |
}; | |
StdOpcodeBuilder.prototype.popScope = function popScope() { | |
this.push(23 /* PopScope */); | |
}; | |
StdOpcodeBuilder.prototype.prepareArgs = function prepareArgs(state) { | |
this.push(79 /* PrepareArgs */, state); | |
}; | |
StdOpcodeBuilder.prototype.createComponent = function createComponent(state, hasDefault) { | |
var flag = hasDefault | 0; | |
this.push(81 /* CreateComponent */, flag, state); | |
}; | |
StdOpcodeBuilder.prototype.registerComponentDestructor = function registerComponentDestructor(state) { | |
this.push(82 /* RegisterComponentDestructor */, state); | |
}; | |
StdOpcodeBuilder.prototype.putComponentOperations = function putComponentOperations() { | |
this.push(83 /* PutComponentOperations */); | |
}; | |
StdOpcodeBuilder.prototype.getComponentSelf = function getComponentSelf(state) { | |
this.push(84 /* GetComponentSelf */, state); | |
}; | |
StdOpcodeBuilder.prototype.getComponentTagName = function getComponentTagName(state) { | |
this.push(85 /* GetComponentTagName */, state); | |
}; | |
StdOpcodeBuilder.prototype.getComponentLayout = function getComponentLayout(state) { | |
this.push(86 /* GetComponentLayout */, state); | |
}; | |
StdOpcodeBuilder.prototype.setupForEval = function setupForEval(state) { | |
this.push(87 /* SetupForEval */, state); | |
}; | |
StdOpcodeBuilder.prototype.invokeComponentLayout = function invokeComponentLayout(state) { | |
this.push(90 /* InvokeComponentLayout */, state); | |
}; | |
StdOpcodeBuilder.prototype.didCreateElement = function didCreateElement(state) { | |
this.push(93 /* DidCreateElement */, state); | |
}; | |
StdOpcodeBuilder.prototype.didRenderLayout = function didRenderLayout(state) { | |
this.push(94 /* DidRenderLayout */, state); | |
}; | |
StdOpcodeBuilder.prototype.pushFrame = function pushFrame() { | |
this.pushMachine(57 /* PushFrame */); | |
}; | |
StdOpcodeBuilder.prototype.popFrame = function popFrame() { | |
this.pushMachine(58 /* PopFrame */); | |
}; | |
StdOpcodeBuilder.prototype.pushSmallFrame = function pushSmallFrame() { | |
this.pushMachine(59 /* PushSmallFrame */); | |
}; | |
StdOpcodeBuilder.prototype.popSmallFrame = function popSmallFrame() { | |
this.pushMachine(60 /* PopSmallFrame */); | |
}; | |
StdOpcodeBuilder.prototype.invokeVirtual = function invokeVirtual() { | |
this.pushMachine(49 /* InvokeVirtual */); | |
}; | |
StdOpcodeBuilder.prototype.invokeYield = function invokeYield() { | |
this.push(51 /* InvokeYield */); | |
}; | |
StdOpcodeBuilder.prototype.toBoolean = function toBoolean() { | |
this.push(63 /* ToBoolean */); | |
}; | |
StdOpcodeBuilder.prototype.invokePreparedComponent = function invokePreparedComponent(hasBlock, bindableBlocks, bindableAtNames) { | |
var populateLayout = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; | |
this.beginComponentTransaction(); | |
this.pushDynamicScope(); | |
this.createComponent(_vm.Register.s0, hasBlock); | |
// this has to run after createComponent to allow | |
// for late-bound layouts, but a caller is free | |
// to populate the layout earlier if it wants to | |
// and do nothing here. | |
if (populateLayout) populateLayout(); | |
this.registerComponentDestructor(_vm.Register.s0); | |
this.getComponentSelf(_vm.Register.s0); | |
this.pushVirtualRootScope(_vm.Register.s0); | |
this.setVariable(0); | |
this.setupForEval(_vm.Register.s0); | |
if (bindableAtNames) this.setNamedVariables(_vm.Register.s0); | |
if (bindableBlocks) this.setBlocks(_vm.Register.s0); | |
this.pop(); | |
this.invokeComponentLayout(_vm.Register.s0); | |
this.didRenderLayout(_vm.Register.s0); | |
this.popFrame(); | |
this.popScope(); | |
this.popDynamicScope(); | |
this.commitComponentTransaction(); | |
}; | |
StdOpcodeBuilder.prototype.compileInline = function compileInline(sexp) { | |
return this.compiler.compileInline(sexp, this); | |
}; | |
StdOpcodeBuilder.prototype.compileBlock = function compileBlock(name, params, hash, template, inverse) { | |
this.compiler.compileBlock(name, params, hash, template, inverse, this); | |
}; | |
StdOpcodeBuilder.prototype.label = function label(name) { | |
this.labels.label(name, this.nextPos); | |
}; | |
StdOpcodeBuilder.prototype.startLabels = function startLabels() { | |
this.labelsStack.push(new Labels()); | |
}; | |
StdOpcodeBuilder.prototype.stopLabels = function stopLabels() { | |
var label = this.labelsStack.pop(); | |
label.patch(this.encoder); | |
}; | |
StdOpcodeBuilder.prototype.pushCurriedComponent = function pushCurriedComponent() { | |
this.push(74 /* PushCurriedComponent */); | |
}; | |
StdOpcodeBuilder.prototype.pushDynamicComponentInstance = function pushDynamicComponentInstance() { | |
this.push(73 /* PushDynamicComponentInstance */); | |
}; | |
StdOpcodeBuilder.prototype.openDynamicElement = function openDynamicElement() { | |
this.push(34 /* OpenDynamicElement */); | |
}; | |
StdOpcodeBuilder.prototype.flushElement = function flushElement() { | |
this.push(38 /* FlushElement */); | |
}; | |
StdOpcodeBuilder.prototype.closeElement = function closeElement() { | |
this.push(39 /* CloseElement */); | |
}; | |
StdOpcodeBuilder.prototype.putIterator = function putIterator() { | |
this.push(66 /* PutIterator */); | |
}; | |
StdOpcodeBuilder.prototype.enterList = function enterList(start) { | |
this.reserve(64 /* EnterList */); | |
this.labels.target(this.pos, start); | |
}; | |
StdOpcodeBuilder.prototype.exitList = function exitList() { | |
this.push(65 /* ExitList */); | |
}; | |
StdOpcodeBuilder.prototype.iterate = function iterate(breaks) { | |
this.reserve(67 /* Iterate */); | |
this.labels.target(this.pos, breaks); | |
}; | |
StdOpcodeBuilder.prototype.setNamedVariables = function setNamedVariables(state) { | |
this.push(2 /* SetNamedVariables */, state); | |
}; | |
StdOpcodeBuilder.prototype.setBlocks = function setBlocks(state) { | |
this.push(3 /* SetBlocks */, state); | |
}; | |
StdOpcodeBuilder.prototype.setVariable = function setVariable(symbol) { | |
this.push(4 /* SetVariable */, symbol); | |
}; | |
StdOpcodeBuilder.prototype.setBlock = function setBlock(symbol) { | |
this.push(5 /* SetBlock */, symbol); | |
}; | |
StdOpcodeBuilder.prototype.getVariable = function getVariable(symbol) { | |
this.push(6 /* GetVariable */, symbol); | |
}; | |
StdOpcodeBuilder.prototype.getBlock = function getBlock(symbol) { | |
this.push(8 /* GetBlock */, symbol); | |
}; | |
StdOpcodeBuilder.prototype.hasBlock = function hasBlock(symbol) { | |
this.push(9 /* HasBlock */, symbol); | |
}; | |
StdOpcodeBuilder.prototype.concat = function concat(size) { | |
this.push(11 /* Concat */, size); | |
}; | |
StdOpcodeBuilder.prototype.load = function load(register) { | |
this.push(18 /* Load */, register); | |
}; | |
StdOpcodeBuilder.prototype.fetch = function fetch(register) { | |
this.push(19 /* Fetch */, register); | |
}; | |
StdOpcodeBuilder.prototype.dup = function dup() { | |
var register = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _vm.Register.sp; | |
var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | |
return this.push(16 /* Dup */, register, offset); | |
}; | |
StdOpcodeBuilder.prototype.pop = function pop() { | |
var count = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; | |
return this.push(17 /* Pop */, count); | |
}; | |
StdOpcodeBuilder.prototype.returnTo = function returnTo(label) { | |
this.reserveMachine(25 /* ReturnTo */); | |
this.labels.target(this.pos, label); | |
}; | |
StdOpcodeBuilder.prototype.primitiveReference = function primitiveReference() { | |
this.push(14 /* PrimitiveReference */); | |
}; | |
StdOpcodeBuilder.prototype.reifyU32 = function reifyU32() { | |
this.push(15 /* ReifyU32 */); | |
}; | |
StdOpcodeBuilder.prototype.enter = function enter(args) { | |
this.push(61 /* Enter */, args); | |
}; | |
StdOpcodeBuilder.prototype.exit = function exit() { | |
this.push(62 /* Exit */); | |
}; | |
StdOpcodeBuilder.prototype.return = function _return() { | |
this.pushMachine(24 /* Return */); | |
}; | |
StdOpcodeBuilder.prototype.jump = function jump(target) { | |
this.reserveMachine(52 /* Jump */); | |
this.labels.target(this.pos, target); | |
}; | |
StdOpcodeBuilder.prototype.jumpIf = function jumpIf(target) { | |
this.reserve(53 /* JumpIf */); | |
this.labels.target(this.pos, target); | |
}; | |
StdOpcodeBuilder.prototype.jumpUnless = function jumpUnless(target) { | |
this.reserve(54 /* JumpUnless */); | |
this.labels.target(this.pos, target); | |
}; | |
StdOpcodeBuilder.prototype.jumpEq = function jumpEq(value, target) { | |
this.reserveWithOperand(55 /* JumpEq */, value); | |
this.labels.target(this.pos, target); | |
}; | |
StdOpcodeBuilder.prototype.assertSame = function assertSame() { | |
this.push(56 /* AssertSame */); | |
}; | |
StdOpcodeBuilder.prototype.pushEmptyArgs = function pushEmptyArgs() { | |
this.push(77 /* PushEmptyArgs */); | |
}; | |
StdOpcodeBuilder.prototype.switch = function _switch(_opcode, callback) { | |
var _this = this; | |
// Setup the switch DSL | |
var clauses = []; | |
var count = 0; | |
function when(match, callback) { | |
clauses.push({ match: match, callback: callback, label: 'CLAUSE' + count++ }); | |
} | |
// Call the callback | |
callback(when); | |
// Emit the opcodes for the switch | |
this.enter(2); | |
this.assertSame(); | |
this.reifyU32(); | |
this.startLabels(); | |
// First, emit the jump opcodes. We don't need a jump for the last | |
// opcode, since it bleeds directly into its clause. | |
clauses.slice(0, -1).forEach(function (clause) { | |
return _this.jumpEq(clause.match, clause.label); | |
}); | |
// Enumerate the clauses in reverse order. Earlier matches will | |
// require fewer checks. | |
for (var i = clauses.length - 1; i >= 0; i--) { | |
var clause = clauses[i]; | |
this.label(clause.label); | |
this.pop(2); | |
clause.callback(); | |
// The first match is special: it is placed directly before the END | |
// label, so no additional jump is needed at the end of it. | |
if (i !== 0) { | |
this.jump('END'); | |
} | |
} | |
this.label('END'); | |
this.stopLabels(); | |
this.exit(); | |
}; | |
StdOpcodeBuilder.prototype.stdAppend = function stdAppend(trusting) { | |
var _this2 = this; | |
this.switch(this.contentType(), function (when) { | |
when(1 /* String */, function () { | |
if (trusting) { | |
_this2.assertSame(); | |
_this2.appendHTML(); | |
} else { | |
_this2.appendText(); | |
} | |
}); | |
when(0 /* Component */, function () { | |
_this2.pushCurriedComponent(); | |
_this2.pushDynamicComponentInstance(); | |
_this2.invokeBareComponent(); | |
}); | |
when(3 /* SafeString */, function () { | |
_this2.assertSame(); | |
_this2.appendSafeHTML(); | |
}); | |
when(4 /* Fragment */, function () { | |
_this2.assertSame(); | |
_this2.appendDocumentFragment(); | |
}); | |
when(5 /* Node */, function () { | |
_this2.assertSame(); | |
_this2.appendNode(); | |
}); | |
}); | |
}; | |
StdOpcodeBuilder.prototype.populateLayout = function populateLayout(state) { | |
this.push(89 /* PopulateLayout */, state); | |
}; | |
StdOpcodeBuilder.prototype.invokeBareComponent = function invokeBareComponent() { | |
var _this3 = this; | |
this.fetch(_vm.Register.s0); | |
this.dup(_vm.Register.sp, 1); | |
this.load(_vm.Register.s0); | |
this.pushFrame(); | |
this.pushEmptyArgs(); | |
this.prepareArgs(_vm.Register.s0); | |
this.invokePreparedComponent(false, false, true, function () { | |
_this3.getComponentLayout(_vm.Register.s0); | |
_this3.populateLayout(_vm.Register.s0); | |
}); | |
this.load(_vm.Register.s0); | |
}; | |
StdOpcodeBuilder.prototype.isComponent = function isComponent() { | |
this.push(69 /* IsComponent */); | |
}; | |
StdOpcodeBuilder.prototype.contentType = function contentType() { | |
this.push(70 /* ContentType */); | |
}; | |
StdOpcodeBuilder.prototype.pushBlockScope = function pushBlockScope() { | |
this.push(47 /* PushBlockScope */); | |
}; | |
(0, _emberBabel.createClass)(StdOpcodeBuilder, [{ | |
key: 'pos', | |
get: function () { | |
return this.encoder.typePos; | |
} | |
}, { | |
key: 'nextPos', | |
get: function () { | |
return this.encoder.size; | |
} | |
}, { | |
key: 'labels', | |
get: function () { | |
return this.labelsStack.current; | |
} | |
}]); | |
return StdOpcodeBuilder; | |
}(); | |
var OpcodeBuilder = function (_StdOpcodeBuilder) { | |
(0, _emberBabel.inherits)(OpcodeBuilder, _StdOpcodeBuilder); | |
function OpcodeBuilder(compiler, containingLayout) { | |
(0, _emberBabel.classCallCheck)(this, OpcodeBuilder); | |
var _this4 = (0, _emberBabel.possibleConstructorReturn)(this, _StdOpcodeBuilder.call(this, compiler, containingLayout ? containingLayout.block.symbols.length : 0)); | |
_this4.containingLayout = containingLayout; | |
_this4.component = new ComponentBuilder(_this4); | |
_this4.expressionCompiler = expressionCompiler(); | |
_this4.isComponentAttrs = false; | |
_this4.constants = compiler.constants; | |
_this4.stdLib = compiler.stdLib; | |
return _this4; | |
} | |
/// MECHANICS | |
OpcodeBuilder.prototype.setComponentAttrs = function setComponentAttrs(enabled) { | |
this.isComponentAttrs = enabled; | |
}; | |
OpcodeBuilder.prototype.expr = function expr(expression) { | |
if (Array.isArray(expression)) { | |
this.expressionCompiler.compile(expression, this); | |
} else { | |
this.pushPrimitiveReference(expression); | |
} | |
}; | |
OpcodeBuilder.prototype.pushArgs = function pushArgs(names, flags) { | |
var serialized = this.constants.stringArray(names); | |
this.push(76 /* PushArgs */, serialized, flags); | |
}; | |
OpcodeBuilder.prototype.pushYieldableBlock = function pushYieldableBlock(block) { | |
this.pushSymbolTable(block && block.symbolTable); | |
this.pushBlockScope(); | |
this.pushBlock(block); | |
}; | |
OpcodeBuilder.prototype.curryComponent = function curryComponent(definition, | |
/* TODO: attrs: Option<RawInlineBlock>, */params, hash, synthetic) { | |
var referrer = this.containingLayout.referrer; | |
this.pushFrame(); | |
this.compileArgs(params, hash, null, synthetic); | |
this.push(80 /* CaptureArgs */); | |
this.expr(definition); | |
this.push(71 /* CurryComponent */, this.constants.serializable(referrer)); | |
this.popFrame(); | |
this.fetch(_vm.Register.v0); | |
}; | |
OpcodeBuilder.prototype.pushSymbolTable = function pushSymbolTable(table) { | |
if (table) { | |
var constant = this.constants.serializable(table); | |
this.push(48 /* PushSymbolTable */, constant); | |
} else { | |
this.primitive(null); | |
} | |
}; | |
OpcodeBuilder.prototype.invokeComponent = function invokeComponent(capabilities, attrs, params, hash, synthetic, block) { | |
var _this5 = this; | |
var inverse = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; | |
var layout = arguments[7]; | |
this.fetch(_vm.Register.s0); | |
this.dup(_vm.Register.sp, 1); | |
this.load(_vm.Register.s0); | |
this.pushFrame(); | |
var bindableBlocks = !!(block || inverse || attrs); | |
var bindableAtNames = capabilities === true || capabilities.prepareArgs || !!(hash && hash[0].length !== 0); | |
var blocks = { main: block, else: inverse, attrs: attrs }; | |
this.compileArgs(params, hash, blocks, synthetic); | |
this.prepareArgs(_vm.Register.s0); | |
this.invokePreparedComponent(block !== null, bindableBlocks, bindableAtNames, function () { | |
if (layout) { | |
_this5.pushSymbolTable(layout.symbolTable); | |
_this5.pushLayout(layout); | |
_this5.resolveLayout(); | |
} else { | |
_this5.getComponentLayout(_vm.Register.s0); | |
} | |
_this5.populateLayout(_vm.Register.s0); | |
}); | |
this.load(_vm.Register.s0); | |
}; | |
OpcodeBuilder.prototype.invokeStaticComponent = function invokeStaticComponent(capabilities, layout, attrs, params, hash, synthetic, block) { | |
var inverse = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null; | |
var symbolTable = layout.symbolTable; | |
var bailOut = symbolTable.hasEval || capabilities.prepareArgs; | |
if (bailOut) { | |
this.invokeComponent(capabilities, attrs, params, hash, synthetic, block, inverse, layout); | |
return; | |
} | |
this.fetch(_vm.Register.s0); | |
this.dup(_vm.Register.sp, 1); | |
this.load(_vm.Register.s0); | |
var symbols = symbolTable.symbols; | |
if (capabilities.createArgs) { | |
this.pushFrame(); | |
this.compileArgs(null, hash, null, synthetic); | |
} | |
this.beginComponentTransaction(); | |
if (capabilities.dynamicScope) { | |
this.pushDynamicScope(); | |
} | |
if (capabilities.createInstance) { | |
this.createComponent(_vm.Register.s0, block !== null); | |
} | |
if (capabilities.createArgs) { | |
this.popFrame(); | |
} | |
this.pushFrame(); | |
this.registerComponentDestructor(_vm.Register.s0); | |
var bindings = []; | |
this.getComponentSelf(_vm.Register.s0); | |
bindings.push({ symbol: 0, isBlock: false }); | |
for (var i = 0; i < symbols.length; i++) { | |
var symbol = symbols[i]; | |
switch (symbol.charAt(0)) { | |
case '&': | |
var callerBlock = null; | |
if (symbol === '&default') { | |
callerBlock = block; | |
} else if (symbol === '&inverse') { | |
callerBlock = inverse; | |
} else if (symbol === ATTRS_BLOCK) { | |
callerBlock = attrs; | |
} else { | |
throw (0, _util.unreachable)(); | |
} | |
if (callerBlock) { | |
this.pushYieldableBlock(callerBlock); | |
bindings.push({ symbol: i + 1, isBlock: true }); | |
} else { | |
this.pushYieldableBlock(null); | |
bindings.push({ symbol: i + 1, isBlock: true }); | |
} | |
break; | |
case '@': | |
if (!hash) { | |
break; | |
} | |
var keys = hash[0], | |
values = hash[1]; | |
var lookupName = symbol; | |
if (synthetic) { | |
lookupName = symbol.slice(1); | |
} | |
var index = keys.indexOf(lookupName); | |
if (index !== -1) { | |
this.expr(values[index]); | |
bindings.push({ symbol: i + 1, isBlock: false }); | |
} | |
break; | |
} | |
} | |
this.pushRootScope(symbols.length + 1, !!(block || inverse || attrs)); | |
for (var _i = bindings.length - 1; _i >= 0; _i--) { | |
var _bindings$_i = bindings[_i], | |
_symbol = _bindings$_i.symbol, | |
isBlock = _bindings$_i.isBlock; | |
if (isBlock) { | |
this.setBlock(_symbol); | |
} else { | |
this.setVariable(_symbol); | |
} | |
} | |
this.invokeStatic(layout); | |
if (capabilities.createInstance) { | |
this.didRenderLayout(_vm.Register.s0); | |
} | |
this.popFrame(); | |
this.popScope(); | |
if (capabilities.dynamicScope) { | |
this.popDynamicScope(); | |
} | |
this.commitComponentTransaction(); | |
this.load(_vm.Register.s0); | |
}; | |
OpcodeBuilder.prototype.dynamicComponent = function dynamicComponent(definition, attrs, params, hash, synthetic, block) { | |
var _this6 = this; | |
var inverse = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; | |
this.replayable({ | |
args: function () { | |
_this6.expr(definition); | |
_this6.dup(); | |
return 2; | |
}, | |
body: function () { | |
_this6.jumpUnless('ELSE'); | |
_this6.resolveDynamicComponent(_this6.containingLayout.referrer); | |
_this6.pushDynamicComponentInstance(); | |
_this6.invokeComponent(true, attrs, params, hash, synthetic, block, inverse); | |
_this6.label('ELSE'); | |
} | |
}); | |
}; | |
OpcodeBuilder.prototype.yield = function _yield(to, params) { | |
this.compileArgs(params, null, null, false); | |
this.getBlock(to); | |
this.resolveBlock(); | |
this.invokeYield(); | |
this.popScope(); | |
this.popFrame(); | |
}; | |
OpcodeBuilder.prototype.guardedAppend = function guardedAppend(expression, trusting) { | |
this.pushFrame(); | |
this.expr(expression); | |
this.pushMachine(50 /* InvokeStatic */, this.stdLib.getAppend(trusting)); | |
this.popFrame(); | |
}; | |
OpcodeBuilder.prototype.invokeStaticBlock = function invokeStaticBlock(block) { | |
var callerCount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | |
var parameters = block.symbolTable.parameters; | |
var calleeCount = parameters.length; | |
var count = Math.min(callerCount, calleeCount); | |
this.pushFrame(); | |
if (count) { | |
this.pushChildScope(); | |
for (var i = 0; i < count; i++) { | |
this.dup(_vm.Register.fp, callerCount - i); | |
this.setVariable(parameters[i]); | |
} | |
} | |
this.pushBlock(block); | |
this.resolveBlock(); | |
this.invokeVirtual(); | |
if (count) { | |
this.popScope(); | |
} | |
this.popFrame(); | |
}; | |
OpcodeBuilder.prototype.string = function string(_string) { | |
return this.constants.string(_string); | |
}; | |
OpcodeBuilder.prototype.names = function names(_names) { | |
var names = []; | |
for (var i = 0; i < _names.length; i++) { | |
var n = _names[i]; | |
names[i] = this.constants.string(n); | |
} | |
return this.constants.array(names); | |
}; | |
OpcodeBuilder.prototype.symbols = function symbols(_symbols2) { | |
return this.constants.array(_symbols2); | |
}; | |
OpcodeBuilder.prototype.primitive = function primitive(_primitive) { | |
var type = 0 /* NUMBER */; | |
var primitive = void 0; | |
switch (typeof _primitive) { | |
case 'number': | |
if (_primitive % 1 === 0) { | |
if (_primitive > -1) { | |
primitive = _primitive; | |
} else { | |
primitive = this.constants.number(_primitive); | |
type = 4 /* NEGATIVE */; | |
} | |
} else { | |
primitive = this.constants.number(_primitive); | |
type = 1 /* FLOAT */; | |
} | |
break; | |
case 'string': | |
primitive = this.string(_primitive); | |
type = 2 /* STRING */; | |
break; | |
case 'boolean': | |
primitive = _primitive | 0; | |
type = 3 /* BOOLEAN_OR_VOID */; | |
break; | |
case 'object': | |
// assume null | |
primitive = 2; | |
type = 3 /* BOOLEAN_OR_VOID */; | |
break; | |
case 'undefined': | |
primitive = 3; | |
type = 3 /* BOOLEAN_OR_VOID */; | |
break; | |
default: | |
throw new Error('Invalid primitive passed to pushPrimitive'); | |
} | |
var immediate = this.sizeImmediate(primitive << 3 | type, primitive); | |
this.push(13 /* Primitive */, immediate); | |
}; | |
OpcodeBuilder.prototype.sizeImmediate = function sizeImmediate(shifted, primitive) { | |
if (shifted >= 65535 /* MAX_SIZE */ || shifted < 0) { | |
return this.constants.number(primitive) << 3 | 5 /* BIG_NUM */; | |
} | |
return shifted; | |
}; | |
OpcodeBuilder.prototype.pushPrimitiveReference = function pushPrimitiveReference(primitive) { | |
this.primitive(primitive); | |
this.primitiveReference(); | |
}; | |
OpcodeBuilder.prototype.pushComponentDefinition = function pushComponentDefinition(handle) { | |
this.push(72 /* PushComponentDefinition */, this.constants.handle(handle)); | |
}; | |
OpcodeBuilder.prototype.resolveDynamicComponent = function resolveDynamicComponent(referrer) { | |
this.push(75 /* ResolveDynamicComponent */, this.constants.serializable(referrer)); | |
}; | |
OpcodeBuilder.prototype.staticComponentHelper = function staticComponentHelper(tag, hash, template) { | |
var _compiler$resolveLayo = this.compiler.resolveLayoutForTag(tag, this.referrer), | |
handle = _compiler$resolveLayo.handle, | |
capabilities = _compiler$resolveLayo.capabilities, | |
compilable = _compiler$resolveLayo.compilable; | |
if (handle !== null && capabilities !== null) { | |
if (compilable) { | |
if (hash) { | |
for (var i = 0; i < hash.length; i = i + 2) { | |
hash[i][0] = '@' + hash[i][0]; | |
} | |
} | |
this.pushComponentDefinition(handle); | |
this.invokeStaticComponent(capabilities, compilable, null, null, hash, false, template && template); | |
return true; | |
} | |
} | |
return false; | |
}; | |
OpcodeBuilder.prototype.invokePartial = function invokePartial(referrer, symbols, evalInfo) { | |
var _meta = this.constants.serializable(referrer); | |
var _symbols = this.constants.stringArray(symbols); | |
var _evalInfo = this.constants.array(evalInfo); | |
this.push(95 /* InvokePartial */, _meta, _symbols, _evalInfo); | |
}; | |
OpcodeBuilder.prototype.resolveMaybeLocal = function resolveMaybeLocal(name) { | |
this.push(96 /* ResolveMaybeLocal */, this.string(name)); | |
}; | |
OpcodeBuilder.prototype.debugger = function _debugger(symbols, evalInfo) { | |
this.push(97 /* Debugger */, this.constants.stringArray(symbols), this.constants.array(evalInfo)); | |
}; | |
OpcodeBuilder.prototype.text = function text(_text) { | |
this.push(26 /* Text */, this.constants.string(_text)); | |
}; | |
OpcodeBuilder.prototype.openPrimitiveElement = function openPrimitiveElement(tag) { | |
this.push(33 /* OpenElement */, this.constants.string(tag)); | |
}; | |
OpcodeBuilder.prototype.modifier = function modifier(locator, params, hash) { | |
this.pushFrame(); | |
this.compileArgs(params, hash, null, true); | |
this.push(40 /* Modifier */, this.constants.handle(locator)); | |
this.popFrame(); | |
}; | |
OpcodeBuilder.prototype.comment = function comment(_comment) { | |
var comment = this.constants.string(_comment); | |
this.push(27 /* Comment */, comment); | |
}; | |
OpcodeBuilder.prototype.dynamicAttr = function dynamicAttr(_name, _namespace, trusting) { | |
var name = this.constants.string(_name); | |
var namespace = _namespace ? this.constants.string(_namespace) : 0; | |
if (this.isComponentAttrs) { | |
this.push(37 /* ComponentAttr */, name, trusting === true ? 1 : 0, namespace); | |
} else { | |
this.push(36 /* DynamicAttr */, name, trusting === true ? 1 : 0, namespace); | |
} | |
}; | |
OpcodeBuilder.prototype.staticAttr = function staticAttr(_name, _namespace, _value) { | |
var name = this.constants.string(_name); | |
var namespace = _namespace ? this.constants.string(_namespace) : 0; | |
if (this.isComponentAttrs) { | |
this.pushPrimitiveReference(_value); | |
this.push(37 /* ComponentAttr */, name, 1, namespace); | |
} else { | |
var value = this.constants.string(_value); | |
this.push(35 /* StaticAttr */, name, value, namespace); | |
} | |
}; | |
OpcodeBuilder.prototype.hasBlockParams = function hasBlockParams(to) { | |
this.getBlock(to); | |
this.resolveBlock(); | |
this.push(10 /* HasBlockParams */); | |
}; | |
OpcodeBuilder.prototype.getProperty = function getProperty(key) { | |
this.push(7 /* GetProperty */, this.string(key)); | |
}; | |
OpcodeBuilder.prototype.helper = function helper(_helper, params, hash) { | |
this.pushFrame(); | |
this.compileArgs(params, hash, null, true); | |
this.push(1 /* Helper */, this.constants.handle(_helper)); | |
this.popFrame(); | |
this.fetch(_vm.Register.v0); | |
}; | |
OpcodeBuilder.prototype.bindDynamicScope = function bindDynamicScope(_names) { | |
this.push(43 /* BindDynamicScope */, this.names(_names)); | |
}; | |
OpcodeBuilder.prototype.replayable = function replayable(_ref) { | |
var args = _ref.args, | |
body = _ref.body; | |
// Start a new label frame, to give END and RETURN | |
// a unique meaning. | |
this.startLabels(); | |
this.pushFrame(); | |
// If the body invokes a block, its return will return to | |
// END. Otherwise, the return in RETURN will return to END. | |
this.returnTo('ENDINITIAL'); | |
// Push the arguments onto the stack. The args() function | |
// tells us how many stack elements to retain for re-execution | |
// when updating. | |
var count = args(); | |
// Start a new updating closure, remembering `count` elements | |
// from the stack. Everything after this point, and before END, | |
// will execute both initially and to update the block. | |
// | |
// The enter and exit opcodes also track the area of the DOM | |
// associated with this block. If an assertion inside the block | |
// fails (for example, the test value changes from true to false | |
// in an #if), the DOM is cleared and the program is re-executed, | |
// restoring `count` elements to the stack and executing the | |
// instructions between the enter and exit. | |
this.enter(count); | |
// Evaluate the body of the block. The body of the block may | |
// return, which will jump execution to END during initial | |
// execution, and exit the updating routine. | |
body(); | |
// All execution paths in the body should run the FINALLY once | |
// they are done. It is executed both during initial execution | |
// and during updating execution. | |
this.label('FINALLY'); | |
// Finalize the DOM. | |
this.exit(); | |
// In initial execution, this is a noop: it returns to the | |
// immediately following opcode. In updating execution, this | |
// exits the updating routine. | |
this.return(); | |
// Cleanup code for the block. Runs on initial execution | |
// but not on updating. | |
this.label('ENDINITIAL'); | |
this.popFrame(); | |
this.stopLabels(); | |
}; | |
OpcodeBuilder.prototype.replayableIf = function replayableIf(_ref2) { | |
var _this7 = this; | |
var args = _ref2.args, | |
ifTrue = _ref2.ifTrue, | |
ifFalse = _ref2.ifFalse; | |
this.replayable({ | |
args: args, | |
body: function () { | |
// If the conditional is false, jump to the ELSE label. | |
_this7.jumpUnless('ELSE'); | |
// Otherwise, execute the code associated with the true branch. | |
ifTrue(); | |
// We're done, so return. In the initial execution, this runs | |
// the cleanup code. In the updating VM, it exits the updating | |
// routine. | |
_this7.jump('FINALLY'); | |
_this7.label('ELSE'); | |
// If the conditional is false, and code associatied ith the | |
// false branch was provided, execute it. If there was no code | |
// associated with the false branch, jumping to the else statement | |
// has no other behavior. | |
if (ifFalse) { | |
ifFalse(); | |
} | |
} | |
}); | |
}; | |
OpcodeBuilder.prototype.inlineBlock = function inlineBlock(block) { | |
return new CompilableBlock(this.compiler, { | |
block: block, | |
containingLayout: this.containingLayout | |
}); | |
}; | |
OpcodeBuilder.prototype.evalSymbols = function evalSymbols() { | |
var block = this.containingLayout.block; | |
return block.hasEval ? block.symbols : null; | |
}; | |
OpcodeBuilder.prototype.compileParams = function compileParams(params) { | |
if (!params) return 0; | |
for (var i = 0; i < params.length; i++) { | |
this.expr(params[i]); | |
} | |
return params.length; | |
}; | |
OpcodeBuilder.prototype.compileArgs = function compileArgs(params, hash, blocks, synthetic) { | |
if (blocks) { | |
this.pushYieldableBlock(blocks.main); | |
this.pushYieldableBlock(blocks.else); | |
this.pushYieldableBlock(blocks.attrs); | |
} | |
var count = this.compileParams(params); | |
var flags = count << 4; | |
if (synthetic) flags |= 8; | |
if (blocks) { | |
flags |= 7; | |
} | |
var names = _util.EMPTY_ARRAY; | |
if (hash) { | |
names = hash[0]; | |
var val = hash[1]; | |
for (var i = 0; i < val.length; i++) { | |
this.expr(val[i]); | |
} | |
} | |
this.pushArgs(names, flags); | |
}; | |
OpcodeBuilder.prototype.template = function template(block) { | |
if (!block) return null; | |
return this.inlineBlock(block); | |
}; | |
(0, _emberBabel.createClass)(OpcodeBuilder, [{ | |
key: 'referrer', | |
get: function () { | |
return this.containingLayout && this.containingLayout.referrer; | |
} | |
}]); | |
return OpcodeBuilder; | |
}(StdOpcodeBuilder); | |
var LazyOpcodeBuilder = function (_OpcodeBuilder) { | |
(0, _emberBabel.inherits)(LazyOpcodeBuilder, _OpcodeBuilder); | |
function LazyOpcodeBuilder() { | |
(0, _emberBabel.classCallCheck)(this, LazyOpcodeBuilder); | |
return (0, _emberBabel.possibleConstructorReturn)(this, _OpcodeBuilder.apply(this, arguments)); | |
} | |
LazyOpcodeBuilder.prototype.pushBlock = function pushBlock(block) { | |
if (block) { | |
this.pushOther(block); | |
} else { | |
this.primitive(null); | |
} | |
}; | |
LazyOpcodeBuilder.prototype.resolveBlock = function resolveBlock() { | |
this.push(46 /* CompileBlock */); | |
}; | |
LazyOpcodeBuilder.prototype.pushLayout = function pushLayout(layout) { | |
if (layout) { | |
this.pushOther(layout); | |
} else { | |
this.primitive(null); | |
} | |
}; | |
LazyOpcodeBuilder.prototype.resolveLayout = function resolveLayout() { | |
this.push(46 /* CompileBlock */); | |
}; | |
LazyOpcodeBuilder.prototype.invokeStatic = function invokeStatic(compilable) { | |
this.pushOther(compilable); | |
this.push(46 /* CompileBlock */); | |
this.pushMachine(49 /* InvokeVirtual */); | |
}; | |
LazyOpcodeBuilder.prototype.pushOther = function pushOther(value) { | |
this.push(12 /* Constant */, this.other(value)); | |
}; | |
LazyOpcodeBuilder.prototype.other = function other(value) { | |
return this.constants.other(value); | |
}; | |
return LazyOpcodeBuilder; | |
}(OpcodeBuilder); | |
var EagerOpcodeBuilder = function (_OpcodeBuilder2) { | |
(0, _emberBabel.inherits)(EagerOpcodeBuilder, _OpcodeBuilder2); | |
function EagerOpcodeBuilder() { | |
(0, _emberBabel.classCallCheck)(this, EagerOpcodeBuilder); | |
return (0, _emberBabel.possibleConstructorReturn)(this, _OpcodeBuilder2.apply(this, arguments)); | |
} | |
EagerOpcodeBuilder.prototype.pushBlock = function pushBlock(block) { | |
var handle = block ? block.compile() : null; | |
this.primitive(handle); | |
}; | |
EagerOpcodeBuilder.prototype.resolveBlock = function resolveBlock() { | |
return; | |
}; | |
EagerOpcodeBuilder.prototype.pushLayout = function pushLayout(layout) { | |
if (layout) { | |
this.primitive(layout.compile()); | |
} else { | |
this.primitive(null); | |
} | |
}; | |
EagerOpcodeBuilder.prototype.resolveLayout = function resolveLayout() {}; | |
EagerOpcodeBuilder.prototype.invokeStatic = function invokeStatic(compilable) { | |
var handle = compilable.compile(); | |
// If the handle for the invoked component is not yet known (for example, | |
// because this is a recursive invocation and we're still compiling), push a | |
// function that will produce the correct handle when the heap is | |
// serialized. | |
if (handle === PLACEHOLDER_HANDLE$1) { | |
this.pushMachine(50 /* InvokeStatic */, function () { | |
return compilable.compile(); | |
}); | |
} else { | |
this.pushMachine(50 /* InvokeStatic */, handle); | |
} | |
}; | |
return EagerOpcodeBuilder; | |
}(OpcodeBuilder); | |
var LazyCompiler = function (_AbstractCompiler) { | |
(0, _emberBabel.inherits)(LazyCompiler, _AbstractCompiler); | |
// FIXME: turn to static method | |
function LazyCompiler(lookup, resolver, macros) { | |
(0, _emberBabel.classCallCheck)(this, LazyCompiler); | |
var constants = new _program.LazyConstants(resolver); | |
var program = new _program.Program(constants); | |
return (0, _emberBabel.possibleConstructorReturn)(this, _AbstractCompiler.call(this, macros, program, lookup)); | |
} | |
LazyCompiler.prototype.builderFor = function builderFor(containingLayout) { | |
return new LazyOpcodeBuilder(this, containingLayout); | |
}; | |
return LazyCompiler; | |
}(AbstractCompiler); | |
var PartialDefinition = function () { | |
function PartialDefinition(name, // for debugging | |
template) { | |
(0, _emberBabel.classCallCheck)(this, PartialDefinition); | |
this.name = name; | |
this.template = template; | |
} | |
PartialDefinition.prototype.getPartial = function getPartial() { | |
var partial = this.template.asPartial(); | |
var handle = partial.compile(); | |
return { symbolTable: partial.symbolTable, handle: handle }; | |
}; | |
return PartialDefinition; | |
}(); | |
var clientId = 0; | |
function templateFactory(_ref3) { | |
var templateId = _ref3.id, | |
meta = _ref3.meta, | |
block = _ref3.block; | |
var parsedBlock = void 0; | |
var id = templateId || 'client-' + clientId++; | |
var create = function (compiler, envMeta) { | |
var newMeta = envMeta ? (0, _util.assign)({}, envMeta, meta) : meta; | |
if (!parsedBlock) { | |
parsedBlock = JSON.parse(block); | |
} | |
return new TemplateImpl(compiler, { id: id, block: parsedBlock, referrer: newMeta }); | |
}; | |
return { id: id, meta: meta, create: create }; | |
} | |
var TemplateImpl = function () { | |
function TemplateImpl(compiler, parsedLayout) { | |
(0, _emberBabel.classCallCheck)(this, TemplateImpl); | |
this.compiler = compiler; | |
this.parsedLayout = parsedLayout; | |
this.layout = null; | |
this.partial = null; | |
this.wrappedLayout = null; | |
var block = parsedLayout.block; | |
this.symbols = block.symbols; | |
this.hasEval = block.hasEval; | |
this.referrer = parsedLayout.referrer; | |
this.id = parsedLayout.id || 'client-' + clientId++; | |
} | |
TemplateImpl.prototype.asLayout = function asLayout() { | |
if (this.layout) return this.layout; | |
return this.layout = new CompilableProgram(this.compiler, (0, _polyfills.assign)({}, this.parsedLayout, { asPartial: false })); | |
}; | |
TemplateImpl.prototype.asPartial = function asPartial() { | |
if (this.partial) return this.partial; | |
return this.layout = new CompilableProgram(this.compiler, (0, _polyfills.assign)({}, this.parsedLayout, { asPartial: true })); | |
}; | |
TemplateImpl.prototype.asWrappedLayout = function asWrappedLayout() { | |
if (this.wrappedLayout) return this.wrappedLayout; | |
return this.wrappedLayout = new WrappedBuilder(this.compiler, (0, _polyfills.assign)({}, this.parsedLayout, { asPartial: false })); | |
}; | |
return TemplateImpl; | |
}(); | |
exports.ATTRS_BLOCK = ATTRS_BLOCK; | |
exports.Macros = Macros; | |
exports.LazyCompiler = LazyCompiler; | |
exports.compile = compile; | |
exports.AbstractCompiler = AbstractCompiler; | |
exports.debugCompiler = debugCompiler; | |
exports.CompilableBlock = CompilableBlock; | |
exports.CompilableProgram = CompilableProgram; | |
exports.LazyOpcodeBuilder = LazyOpcodeBuilder; | |
exports.EagerOpcodeBuilder = EagerOpcodeBuilder; | |
exports.OpcodeBuilder = OpcodeBuilder; | |
exports.StdOpcodeBuilder = StdOpcodeBuilder; | |
exports.PartialDefinition = PartialDefinition; | |
exports.templateFactory = templateFactory; | |
exports.debug = debug; | |
exports.debugSlice = debugSlice; | |
exports.logOpcode = logOpcode; | |
exports.WrappedBuilder = WrappedBuilder; | |
exports.PLACEHOLDER_HANDLE = PLACEHOLDER_HANDLE; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment