ember-material-icons
Version:
Google Material icons for your ember-cli app
354 lines (272 loc) • 9.7 kB
text/typescript
import { SymbolTable } from '@glimmer/interfaces';
import { Blocks, Inlines, populateBuiltins } from './syntax/functions';
import { Constants } from './opcodes';
import * as Simple from './dom/interfaces';
import { DOMChanges, DOMTreeConstruction } from './dom/helper';
import { Reference, PathReference, OpaqueIterable } from '@glimmer/reference';
import { UNDEFINED_REFERENCE, ConditionalReference } from './references';
import {
defaultManagers,
AttributeManager
} from './dom/attribute-managers';
import {
PartialDefinition
} from './partial';
import {
Component,
ComponentManager,
ComponentDefinition
} from './component/interfaces';
import {
ModifierManager
} from './modifier/interfaces';
import {
Option,
Destroyable,
Opaque,
HasGuid,
ensureGuid,
expect,
assert
} from '@glimmer/util';
import {
TemplateMeta
} from '@glimmer/wire-format';
import { EvaluatedArgs } from './compiled/expressions/args';
import { InlineBlock } from './scanner';
import { PublicVM } from './vm/append';
export type ScopeSlot = PathReference<Opaque> | InlineBlock | EvaluatedArgs;
export interface DynamicScope {
get(key: string): PathReference<Opaque>;
set(key: string, reference: PathReference<Opaque>): PathReference<Opaque>;
child(): DynamicScope;
}
export class Scope {
static root(self: PathReference<Opaque>, size = 0) {
let refs: PathReference<Opaque>[] = new Array(size + 1);
for (let i = 0; i <= size; i++) {
refs[i] = UNDEFINED_REFERENCE;
}
return new Scope(refs).init({ self });
}
// the 0th slot is `self`
private slots: ScopeSlot[];
private callerScope: Option<Scope> = null;
constructor(references: ScopeSlot[], callerScope: Option<Scope> = null) {
this.slots = references;
this.callerScope = callerScope;
}
init({ self }: { self: PathReference<Opaque> }): this {
this.slots[0] = self;
return this;
}
getSelf(): PathReference<Opaque> {
return this.slots[0] as PathReference<Opaque>;
}
getSymbol(symbol: number): PathReference<Opaque> {
return this.slots[symbol] as PathReference<Opaque>;
}
getBlock(symbol: number): InlineBlock {
return this.slots[symbol] as InlineBlock;
}
getPartialArgs(symbol: number): EvaluatedArgs {
return this.slots[symbol] as EvaluatedArgs;
}
bindSymbol(symbol: number, value: PathReference<Opaque>) {
this.slots[symbol] = value;
}
bindBlock(symbol: number, value: InlineBlock) {
this.slots[symbol] = value;
}
bindPartialArgs(symbol: number, value: EvaluatedArgs) {
this.slots[symbol] = value;
}
bindCallerScope(scope: Scope) {
this.callerScope = scope;
}
getCallerScope(): Option<Scope> {
return this.callerScope;
}
child(): Scope {
return new Scope(this.slots.slice(), this.callerScope);
}
}
class Transaction {
public scheduledInstallManagers: ModifierManager<Opaque>[] = [];
public scheduledInstallModifiers: Object[] = [];
public scheduledUpdateModifierManagers: ModifierManager<Opaque>[] = [];
public scheduledUpdateModifiers: Object[] = [];
public createdComponents: Component[] = [];
public createdManagers: ComponentManager<Component>[] = [];
public updatedComponents: Component[] = [];
public updatedManagers: ComponentManager<Component>[] = [];
public destructors: Destroyable[] = [];
didCreate<T>(component: T, manager: ComponentManager<T>) {
this.createdComponents.push(component);
this.createdManagers.push(manager);
}
didUpdate<T>(component: T, manager: ComponentManager<T>) {
this.updatedComponents.push(component);
this.updatedManagers.push(manager);
}
scheduleInstallModifier<T>(modifier: T, manager: ModifierManager<T>) {
this.scheduledInstallManagers.push(manager);
this.scheduledInstallModifiers.push(modifier);
}
scheduleUpdateModifier<T>(modifier: T, manager: ModifierManager<T>) {
this.scheduledUpdateModifierManagers.push(manager);
this.scheduledUpdateModifiers.push(modifier);
}
didDestroy(d: Destroyable) {
this.destructors.push(d);
}
commit() {
let { createdComponents, createdManagers } = this;
for (let i=0; i<createdComponents.length; i++) {
let component = createdComponents[i];
let manager = createdManagers[i];
manager.didCreate(component);
}
let { updatedComponents, updatedManagers } = this;
for (let i=0; i<updatedComponents.length; i++) {
let component = updatedComponents[i];
let manager = updatedManagers[i];
manager.didUpdate(component);
}
let { destructors } = this;
for (let i=0; i<destructors.length; i++) {
destructors[i].destroy();
}
let { scheduledInstallManagers, scheduledInstallModifiers } = this;
for (let i = 0; i < scheduledInstallManagers.length; i++) {
let manager = scheduledInstallManagers[i];
let modifier = scheduledInstallModifiers[i];
manager.install(modifier);
}
let { scheduledUpdateModifierManagers, scheduledUpdateModifiers } = this;
for (let i = 0; i < scheduledUpdateModifierManagers.length; i++) {
let manager = scheduledUpdateModifierManagers[i];
let modifier = scheduledUpdateModifiers[i];
manager.update(modifier);
}
}
}
export class Opcode {
public offset = 0;
constructor(private array: Uint32Array | Array<number>) {}
get type() {
return this.array[this.offset];
}
get op1() {
return this.array[this.offset + 1];
}
get op2() {
return this.array[this.offset + 2];
}
get op3() {
return this.array[this.offset + 3];
}
}
export class Program {
[key: number]: never;
private opcodes: number[] = [];
private _offset = 0;
private _opcode: Opcode;
constructor() {
this._opcode = new Opcode(this.opcodes);
}
get next(): number {
return this._offset;
}
get current(): number {
return this._offset - 4;
}
opcode(offset: number): Opcode {
this._opcode.offset = offset;
return this._opcode;
}
set(pos: number, type: number, op1 = 0, op2 = 0, op3 = 0) {
this.opcodes[pos] = type;
this.opcodes[pos + 1] = op1;
this.opcodes[pos + 2] = op2;
this.opcodes[pos + 3] = op3;
}
push(type: number, op1 = 0, op2 = 0, op3 = 0): number {
let offset = this._offset;
this.opcodes[this._offset++] = type;
this.opcodes[this._offset++] = op1;
this.opcodes[this._offset++] = op2;
this.opcodes[this._offset++] = op3;
return offset;
}
}
export abstract class Environment {
protected updateOperations: DOMChanges;
protected appendOperations: DOMTreeConstruction;
private _macros: Option<{ blocks: Blocks, inlines: Inlines }> = null;
private _transaction: Option<Transaction> = null;
public constants: Constants = new Constants();
public program = new Program();
constructor({ appendOperations, updateOperations }: { appendOperations: DOMTreeConstruction, updateOperations: DOMChanges }) {
this.appendOperations = appendOperations;
this.updateOperations = updateOperations;
}
toConditionalReference(reference: Reference<Opaque>): Reference<boolean> {
return new ConditionalReference(reference);
}
abstract iterableFor(reference: Reference<Opaque>, args: EvaluatedArgs): OpaqueIterable;
abstract protocolForURL(s: string): string;
getAppendOperations(): DOMTreeConstruction { return this.appendOperations; }
getDOM(): DOMChanges { return this.updateOperations; }
getIdentity(object: HasGuid): string {
return ensureGuid(object) + '';
}
begin() {
assert(!this._transaction, 'Cannot start a nested transaction');
this._transaction = new Transaction();
}
private get transaction(): Transaction {
return expect(this._transaction, 'must be in a transaction');
}
didCreate<T>(component: T, manager: ComponentManager<T>) {
this.transaction.didCreate(component, manager);
}
didUpdate<T>(component: T, manager: ComponentManager<T>) {
this.transaction.didUpdate(component, manager);
}
scheduleInstallModifier<T>(modifier: T, manager: ModifierManager<T>) {
this.transaction.scheduleInstallModifier(modifier, manager);
}
scheduleUpdateModifier<T>(modifier: T, manager: ModifierManager<T>) {
this.transaction.scheduleUpdateModifier(modifier, manager);
}
didDestroy(d: Destroyable) {
this.transaction.didDestroy(d);
}
commit() {
this.transaction.commit();
this._transaction = null;
}
attributeFor(element: Simple.Element, attr: string, isTrusting: boolean, namespace?: string): AttributeManager {
return defaultManagers(element, attr, isTrusting, namespace === undefined ? null : namespace);
}
macros(): { blocks: Blocks, inlines: Inlines } {
let macros = this._macros;
if (!macros) {
this._macros = macros = populateBuiltins();
}
return macros;
}
abstract hasHelper(helperName: string, blockMeta: TemplateMeta): boolean;
abstract lookupHelper(helperName: string, blockMeta: TemplateMeta): Helper;
abstract hasModifier(modifierName: string, blockMeta: TemplateMeta): boolean;
abstract lookupModifier(modifierName: string, blockMeta: TemplateMeta): ModifierManager<Opaque>;
abstract hasComponentDefinition(tagName: string, symbolTable: SymbolTable): boolean;
abstract getComponentDefinition(tagName: string, symbolTable: SymbolTable): ComponentDefinition<Opaque>;
abstract hasPartial(partialName: string, symbolTable: SymbolTable): boolean;
abstract lookupPartial(PartialName: string, symbolTable: SymbolTable): PartialDefinition<TemplateMeta>;
}
export default Environment;
export interface Helper {
(vm: PublicVM, args: EvaluatedArgs, symbolTable: SymbolTable): PathReference<Opaque>;
}