Skip to content

Commit

Permalink
Continue fleshing out {{-in-element.
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Jackson committed Sep 25, 2016
1 parent c5867c7 commit ad19235
Show file tree
Hide file tree
Showing 9 changed files with 515 additions and 29 deletions.
4 changes: 4 additions & 0 deletions packages/glimmer-runtime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ export {
default as WithDynamicVarsSyntax
} from './lib/syntax/builtins/with-dynamic-vars';

export {
default as InElementSyntax
} from './lib/syntax/builtins/in-element';

export { PublicVM as VM, UpdatingVM, RenderResult } from './lib/vm';

export { SafeString, isSafeString } from './lib/upsert';
Expand Down
37 changes: 22 additions & 15 deletions packages/glimmer-runtime/lib/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,15 @@ export interface LastNode {
}

class First {
private node: Node;

constructor(node) {
this.node = node;
}
constructor(private node: Node) { }

firstNode(): Node {
return this.node;
}
}

class Last {
private node: Node;

constructor(node) {
this.node = node;
}
constructor(private node: Node) { }

lastNode(): Node {
return this.node;
Expand Down Expand Up @@ -151,12 +143,15 @@ export class ElementStack implements Cursor {
return tracker;
}

private pushBlockTracker(tracker: Tracker) {
private pushBlockTracker(tracker: Tracker, isRemote = false) {
let current = this.blockStack.current;

if (current !== null) {
current.newDestroyable(tracker);
current.newBounds(tracker);

if (!isRemote) {
current.newBounds(tracker);
}
}

this.blockStack.push(tracker);
Expand Down Expand Up @@ -207,9 +202,13 @@ export class ElementStack implements Cursor {
pushRemoteElement(element: Simple.Element) {
this.pushElement(element);

let tracker = new SimpleBlockTracker(this.element);
this.pushBlockTracker(tracker);
return tracker;
let tracker = new RemoteBlockTracker(element);
this.pushBlockTracker(tracker, true);
}

popRemoteElement() {
this.popBlock();
this.popElement();
}

private pushElement(element: Simple.Element) {
Expand Down Expand Up @@ -346,6 +345,14 @@ export class SimpleBlockTracker implements Tracker {
}
}

class RemoteBlockTracker extends SimpleBlockTracker {
destroy() {
super.destroy();

clear(this);
}
}

export interface UpdatableTracker extends Tracker {
reset(env: Environment);
}
Expand Down
12 changes: 12 additions & 0 deletions packages/glimmer-runtime/lib/compiled/opcodes/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,18 @@ export abstract class BasicOpcodeBuilder extends StatementCompilationBufferProxy

// vm

pushRemoteElement() {
this.append(new dom.PushRemoteElementOpcode());
}

popRemoteElement() {
this.append(new dom.PopRemoteElementOpcode());
}

popElement() {
this.append(new dom.PopElementOpcode());
}

label(name: string) {
this.append(this.labelFor(name));
}
Expand Down
29 changes: 26 additions & 3 deletions packages/glimmer-runtime/lib/compiled/opcodes/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ValueReference } from '../../compiled/expressions/value';
import { CompiledArgs, EvaluatedArgs } from '../../compiled/expressions/args';
import { AttributeManager } from '../../dom/attribute-managers';
import { ElementOperations } from '../../builder';
import { Assert } from './vm';

export class TextOpcode extends Opcode {
public type = "text";
Expand Down Expand Up @@ -66,8 +67,8 @@ export class PushRemoteElementOpcode extends Opcode {
public type = "push-remote-element";

evaluate(vm: VM) {
let reference = vm.frame.getOperand();
let cache = isConst(reference) ? undefined : new ReferenceCache(reference);
let reference = vm.frame.getOperand<Simple.Element>();
let cache = isConstReference(reference) ? undefined : new ReferenceCache(reference);
let element = cache ? cache.peek() : reference.value();

vm.stack().pushRemoteElement(element);
Expand All @@ -81,11 +82,19 @@ export class PushRemoteElementOpcode extends Opcode {
return {
guid: this._guid,
type: this.type,
args: [JSON.stringify(this.tag)]
args: ['$OPERAND']
};
}
}

export class PopRemoteElementOpcode extends Opcode {
public type = "pop-remote-element";

evaluate(vm: VM) {
vm.stack().popRemoteElement();
}
}

export class OpenComponentElementOpcode extends Opcode {
public type = "open-component-element";

Expand Down Expand Up @@ -369,6 +378,20 @@ export class CloseElementOpcode extends Opcode {
}
}

export class PopElementOpcode extends Opcode {
public type = "pop-element";

evaluate(vm: VM) {
vm.stack().popElement();
}
}

export interface StaticAttrOptions {
namespace: string;
name: string;
value: string;
}

export class StaticAttrOpcode extends Opcode {
public type = "static-attr";

Expand Down
34 changes: 34 additions & 0 deletions packages/glimmer-runtime/lib/syntax/builtins/in-element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {
Statement as StatementSyntax
} from '../../syntax';

import OpcodeBuilderDSL from '../../compiled/opcodes/builder';
import * as Syntax from '../core';
import Environment from '../../environment';

export default class InElementSyntax extends StatementSyntax {
type = "in-element-statement";

public args: Syntax.Args;
public templates: Syntax.Templates;
public isStatic = false;

constructor({ args, templates }: { args: Syntax.Args, templates: Syntax.Templates }) {
super();
this.args = args;
this.templates = templates;
}

compile(dsl: OpcodeBuilderDSL, env: Environment) {
let { args, templates } = this;

dsl.block({ templates, args }, (dsl, BEGIN, END) => {
dsl.putArgs(args);
dsl.test('simple');
dsl.jumpUnless(END);
dsl.pushRemoteElement();
dsl.evaluate('default');
dsl.popRemoteElement();
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ export default class WithDynamicVarsSyntax extends StatementSyntax {
compile(dsl: OpcodeBuilderDSL, env: Environment) {
let { args, templates } = this;

dsl.block({ templates, args }, (dsl) => {
dsl.pushRemoteElement();
dsl.unit({ templates }, dsl => {
dsl.putArgs(args);
dsl.pushDynamicScope();
dsl.bindDynamicScope(args.named.keys);
dsl.evaluate('default');
dsl.popElement();
dsl.popDynamicScope();
});
}
}
16 changes: 8 additions & 8 deletions packages/glimmer-runtime/tests/ember-component-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { equalTokens, stripTight } from "glimmer-test-helpers";

import { CLASS_META, UpdatableReference, setProperty as set } from 'glimmer-object-reference';

class EmberishRootView extends EmberObject {
export class EmberishRootView extends EmberObject {
private parent: Element;
protected _result: RenderResult;
protected template: Template<{}>;
Expand Down Expand Up @@ -73,7 +73,7 @@ function module(name: string) {

module("Components - generic - props");

function appendViewFor(template: string, context: Object = {}) {
export function appendViewFor(template: string, context: Object = {}) {
class MyRootView extends EmberishRootView {
protected env = env;
protected template = env.compile(template);
Expand All @@ -90,7 +90,7 @@ function appendViewFor(template: string, context: Object = {}) {
return view;
}

function assertAppended(content: string) {
export function assertAppended(content: string) {
equalTokens((<HTMLElement>document.querySelector('#qunit-fixture')), content);
}

Expand Down Expand Up @@ -147,12 +147,12 @@ function assertEmberishElement(...args) {
equalsElement(view.element, tagName, fullAttrs, contents);
}

function assertElementIsEmberishElement(element: Element, tagName: string, attrs: Object, contents: string);
function assertElementIsEmberishElement(element: Element, tagName: string, attrs: Object);
function assertElementIsEmberishElement(element: Element, tagName: string, contents: string);
function assertElementIsEmberishElement(element: Element, tagName: string);
export function assertElementIsEmberishElement(element: Element, tagName: string, attrs: Object, contents: string);
export function assertElementIsEmberishElement(element: Element, tagName: string, attrs: Object);
export function assertElementIsEmberishElement(element: Element, tagName: string, contents: string);
export function assertElementIsEmberishElement(element: Element, tagName: string);

function assertElementIsEmberishElement(element: Element, ...args) {
export function assertElementIsEmberishElement(element: Element, ...args) {
let tagName, attrs, contents;
if (args.length === 2) {
if (typeof args[1] === 'string') [tagName, attrs, contents] = [args[0], {}, args[1]];
Expand Down
Loading

0 comments on commit ad19235

Please sign in to comment.