Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
args,
body,
}: {
args(): { count: number; actions: T };
body(): T;
}): T {
// Push the arguments onto the stack. The args() function
// tells us how many stack elements to retain for re-execution
// when updating.
let { count, actions } = args();
// Start a new label frame, to give END and RETURN
// a unique meaning.
return [
op('StartLabels'),
op(MachineOp.PushFrame),
// If the body invokes a block, its return will return to
// END. Otherwise, the return in RETURN will return to END.
op(MachineOp.ReturnTo, label('ENDINITIAL')),
actions,
// 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
evaluateMachine(opcode: RuntimeOp) {
switch (opcode.type) {
case MachineOp.PushFrame:
return this.pushFrame();
case MachineOp.PopFrame:
return this.popFrame();
case MachineOp.InvokeStatic:
return this.call(opcode.op1);
case MachineOp.InvokeVirtual:
return this.call(this.stack.pop());
case MachineOp.Jump:
return this.goto(opcode.op1);
case MachineOp.Return:
return this.return();
case MachineOp.ReturnTo:
return this.returnTo(opcode.op1);
}
}
body() {
let out: StatementCompileActions = [
op(Op.PutIterator),
op(Op.JumpUnless, label('ELSE')),
op(MachineOp.PushFrame),
op(Op.Dup, $fp, 1),
op(MachineOp.ReturnTo, label('ITER')),
op(Op.EnterList, label('BODY')),
op('Label', 'ITER'),
op(Op.Iterate, label('BREAK')),
op('Label', 'BODY'),
invokeStaticBlockWithStack(unwrap(blocks.get('default')), 2),
op(Op.Pop, 2),
op(MachineOp.Jump, label('FINALLY')),
op('Label', 'BREAK'),
op(Op.ExitList),
op(MachineOp.PopFrame),
op(MachineOp.Jump, label('FINALLY')),
op('Label', 'ELSE'),
];
atNames,
blocks: namedBlocks,
layout,
}: Component): StatementCompileActions {
let bindableBlocks = !!namedBlocks;
let bindableAtNames =
capabilities === true || capabilities.prepareArgs || !!(hash && hash[0].length !== 0);
let blocks = namedBlocks.with('attrs', attrs);
return [
op(Op.Fetch, $s0),
op(Op.Dup, $sp, 1),
op(Op.Load, $s0),
op(MachineOp.PushFrame),
op('Args', { params, hash, blocks, atNames }),
op(Op.PrepareArgs, $s0),
invokePreparedComponent(blocks.has('default'), bindableBlocks, bindableAtNames, () => {
let out: NestedStatementCompileActions;
if (layout) {
out = [
PushSymbolTable(layout.symbolTable),
op('PushCompilable', layout),
op('JitCompileBlock'),
];
} else {
out = [op('GetComponentLayout', $s0)];
}
out.push(op(Op.PopulateLayout, $s0));
export function InvokeStaticBlockWithStack(
block: CompilableBlock,
callerCount: number
): StatementCompileActions {
let { parameters } = block.symbolTable;
let calleeCount = parameters.length;
let count = Math.min(callerCount, calleeCount);
if (count === 0) {
return InvokeStaticBlock(block);
}
let out: StatementCompileActions = [];
out.push(op(MachineOp.PushFrame));
if (count) {
out.push(op(Op.ChildScope));
for (let i = 0; i < count; i++) {
out.push(op(Op.Dup, $fp, callerCount - i));
out.push(op(Op.SetVariable, parameters[i]));
}
}
out.push(op('PushCompilable', block));
out.push(op('JitCompileBlock'));
out.push(op(MachineOp.InvokeVirtual));
if (count) {
out.push(op(Op.PopScope));
export function Call({ handle, params, hash }: CompileHelper): ExpressionCompileActions {
return [
op(MachineOp.PushFrame),
op('SimpleArgs', { params, hash, atNames: false }),
op(Op.Helper, handle),
op(MachineOp.PopFrame),
op(Op.Fetch, $v0),
];
}
ifUnhandled: () => [
op(MachineOp.PushFrame),
op(HighLevelResolutionOpcode.Expr, value),
op(MachineOp.InvokeStatic, {
type: 'stdlib',
value: trusted ? 'trusting-append' : 'cautious-append',
}),
op(MachineOp.PopFrame),
],
});
for (let i = 0; i < count; i++) {
arr[i] = null;
}
return arr;
}
export function opcodeMetadata(op: MachineOp | Op, isMachine: 0 | 1): Option {
let value = isMachine ? MACHINE_METADATA[op] : METADATA[op];
return value || null;
}
const METADATA: Option[] = fillNulls(Op.Size);
const MACHINE_METADATA: Option[] = fillNulls(MachineOp.Size);
MACHINE_METADATA[MachineOp.PushFrame] = {
name: 'PushFrame',
mnemonic: 'pushf',
before: null,
stackChange: 2,
ops: [],
operands: 0,
check: true,
};
MACHINE_METADATA[MachineOp.PopFrame] = {
name: 'PopFrame',
mnemonic: 'popf',
before: null,
stackChange: -2,
ops: [],
operands: 0,