Skip to content

Commit

Permalink
Merge pull request #331 from tildeio/remote-element
Browse files Browse the repository at this point in the history
Implement `{{#-in-element` API.
  • Loading branch information
rwjblue committed Sep 25, 2016
2 parents 73800f6 + ad19235 commit 7c4c900
Show file tree
Hide file tree
Showing 8 changed files with 547 additions and 24 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
54 changes: 38 additions & 16 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 @@ -127,7 +119,7 @@ export class ElementStack implements Cursor {
return this.blockStack.current;
}

private popElement() {
popElement() {
let { elementStack, nextSiblingStack } = this;

let topElement = elementStack.pop();
Expand All @@ -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 @@ -193,16 +188,35 @@ export class ElementStack implements Cursor {

flushElement() {
let parent = this.element;
let element = this.element = this.constructing;
let element = this.constructing;

this.dom.insertBefore(parent, element, this.nextSibling);

this.constructing = null;
this.operations = null;
this.nextSibling = null;

this.pushElement(element);
this.blockStack.current.openElement(element);
}

pushRemoteElement(element: Simple.Element) {
this.pushElement(element);

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

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

private pushElement(element: Simple.Element) {
this.element = element;
this.elementStack.push(element);

this.nextSibling = null;
this.nextSiblingStack.push(null);
this.blockStack.current.openElement(element);
}

newDestroyable(d: Destroyable) {
Expand Down Expand Up @@ -331,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
47 changes: 47 additions & 0 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 @@ -62,6 +63,38 @@ export class OpenPrimitiveElementOpcode extends Opcode {
}
}

export class PushRemoteElementOpcode extends Opcode {
public type = "push-remote-element";

evaluate(vm: VM) {
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);

if (cache) {
vm.updateWith(new Assert(cache));
}
}

toJSON(): OpcodeJSON {
return {
guid: this._guid,
type: this.type,
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 @@ -345,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();
});
}
}
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 7c4c900

Please sign in to comment.