ember-material-icons
Version:
Google Material icons for your ember-cli app
214 lines (165 loc) • 6.15 kB
text/typescript
import { OpcodeJSON, UpdatingOpcode } from '../../opcodes';
import { Assert } from './vm';
import { Component, ComponentManager, ComponentDefinition } from '../../component/interfaces';
import { UpdatingVM } from '../../vm';
import { CompiledArgs, EvaluatedArgs } from '../../compiled/expressions/args';
import { DynamicScope } from '../../environment';
import Bounds from '../../bounds';
import { CONSTANT_TAG, ReferenceCache, combine, isConst, RevisionTag } from '@glimmer/reference';
import { APPEND_OPCODES, OpcodeName as Op } from '../../opcodes';
APPEND_OPCODES.add(Op.PutDynamicComponent, vm => {
let reference = vm.frame.getOperand<ComponentDefinition<Component>>();
let cache = isConst(reference) ? undefined : new ReferenceCache(reference);
let definition = cache ? cache.peek() : reference.value();
vm.frame.setImmediate(definition);
if (cache) {
vm.updateWith(new Assert(cache));
}
});
APPEND_OPCODES.add(Op.PutComponent, (vm, { op1: _component }) => {
let definition = vm.constants.getOther<ComponentDefinition<Component>>(_component);
vm.frame.setImmediate(definition);
});
APPEND_OPCODES.add(Op.OpenComponent, (vm, { op1: _args, op2: _shadow }) => {
let rawArgs = vm.constants.getExpression<CompiledArgs>(_args);
let shadow = vm.constants.getBlock(_shadow);
let definition = vm.frame.getImmediate<ComponentDefinition<Component>>();
let dynamicScope = vm.pushDynamicScope();
let callerScope = vm.scope();
let manager = definition.manager;
let args = manager.prepareArgs(definition, rawArgs.evaluate(vm), dynamicScope);
let hasDefaultBlock = !!args.blocks.default; // TODO Cleanup?
let component = manager.create(vm.env, definition, args, dynamicScope, vm.getSelf(), hasDefaultBlock);
let destructor = manager.getDestructor(component);
if (destructor) vm.newDestroyable(destructor);
let layout = manager.layoutFor(definition, component, vm.env);
let selfRef = manager.getSelf(component);
vm.beginCacheGroup();
vm.stack().pushSimpleBlock();
vm.pushRootScope(selfRef, layout.symbols);
vm.invokeLayout(args, layout, callerScope, component, manager, shadow);
vm.updateWith(new UpdateComponentOpcode(definition.name, component, manager, args, dynamicScope));
});
// export class DidCreateElementOpcode extends Opcode {
// public type = "did-create-element";
// evaluate(vm: VM) {
// let manager = vm.frame.getManager();
// let component = vm.frame.getComponent();
// let action = 'DidCreateElementOpcode#evaluate';
// manager.didCreateElement(component, vm.stack().expectConstructing(action), vm.stack().expectOperations(action));
// }
// toJSON(): OpcodeJSON {
// return {
// guid: this._guid,
// type: this.type,
// args: ["$ARGS"]
// };
// }
// }
APPEND_OPCODES.add(Op.DidCreateElement, vm => {
let manager = vm.frame.getManager();
let component = vm.frame.getComponent();
let action = 'DidCreateElementOpcode#evaluate';
manager.didCreateElement(component, vm.stack().expectConstructing(action), vm.stack().expectOperations(action));
});
// export class ShadowAttributesOpcode extends Opcode {
// public type = "shadow-attributes";
// evaluate(vm: VM) {
// let shadow = vm.frame.getShadow();
// vm.pushCallerScope();
// if (!shadow) return;
// vm.invokeBlock(shadow, EvaluatedArgs.empty());
// }
// toJSON(): OpcodeJSON {
// return {
// guid: this._guid,
// type: this.type,
// args: ["$ARGS"]
// };
// }
// }
// Slow path for non-specialized component invocations. Uses an internal
// named lookup on the args.
APPEND_OPCODES.add(Op.ShadowAttributes, vm => {
let shadow = vm.frame.getShadow();
vm.pushCallerScope();
if (!shadow) return;
vm.invokeBlock(shadow, EvaluatedArgs.empty());
});
// export class DidRenderLayoutOpcode extends Opcode {
// public type = "did-render-layout";
// evaluate(vm: VM) {
// let manager = vm.frame.getManager();
// let component = vm.frame.getComponent();
// let bounds = vm.stack().popBlock();
// manager.didRenderLayout(component, bounds);
// vm.env.didCreate(component, manager);
// vm.updateWith(new DidUpdateLayoutOpcode(manager, component, bounds));
// }
// }
APPEND_OPCODES.add(Op.DidRenderLayout, vm => {
let manager = vm.frame.getManager();
let component = vm.frame.getComponent();
let bounds = vm.stack().popBlock();
manager.didRenderLayout(component, bounds);
vm.env.didCreate(component, manager);
vm.updateWith(new DidUpdateLayoutOpcode(manager, component, bounds));
});
// export class CloseComponentOpcode extends Opcode {
// public type = "close-component";
// evaluate(vm: VM) {
// vm.popScope();
// vm.popDynamicScope();
// vm.commitCacheGroup();
// }
// }
APPEND_OPCODES.add(Op.CloseComponent, vm => {
vm.popScope();
vm.popDynamicScope();
vm.commitCacheGroup();
});
export class UpdateComponentOpcode extends UpdatingOpcode {
public type = "update-component";
constructor(
private name: string,
private component: Component,
private manager: ComponentManager<Component>,
private args: EvaluatedArgs,
private dynamicScope: DynamicScope,
) {
super();
let componentTag = manager.getTag(component);
if (componentTag) {
this.tag = combine([args.tag, componentTag]);
} else {
this.tag = args.tag;
}
}
evaluate(_vm: UpdatingVM) {
let { component, manager, args, dynamicScope } = this;
manager.update(component, args, dynamicScope);
}
toJSON(): OpcodeJSON {
return {
guid: this._guid,
type: this.type,
args: [JSON.stringify(this.name)]
};
}
}
export class DidUpdateLayoutOpcode extends UpdatingOpcode {
public type = "did-update-layout";
public tag: RevisionTag = CONSTANT_TAG;
constructor(
private manager: ComponentManager<Component>,
private component: Component,
private bounds: Bounds
) {
super();
}
evaluate(vm: UpdatingVM) {
let { manager, component, bounds } = this;
manager.didUpdateLayout(component, bounds);
vm.env.didUpdate(component, manager);
}
}