Skip to content

Commit

Permalink
refactor aliases to be controlled by the owned fragment of a section
Browse files Browse the repository at this point in the history
allow partials with a context to supply aliases as well
  • Loading branch information
evs-chris committed Feb 2, 2019
1 parent e52abdf commit cb374fc
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 104 deletions.
8 changes: 8 additions & 0 deletions src/parse/converters/mustache/readPartial.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ export default function readPartial(parser, tag) {
partial.c = {};
refineExpression(context, partial.c);
}

// allow aliases after context
if (parser.matchString(',')) {
aliases = readAliases(parser);
if (aliases && aliases.length) {
partial.z = aliases;
}
}
}

if (type !== '>' && (!partial.c && !partial.z)) {
Expand Down
42 changes: 42 additions & 0 deletions src/view/Fragment.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ import processItems from './helpers/processItems';
import parseJSON from 'utils/parseJSON';
import { createDocumentFragment } from 'utils/dom';
import KeyModel from 'src/model/specials/KeyModel';
import resolve from './resolvers/resolve';

function resolveAliases(aliases, fragment, dest = {}) {
for (let i = 0; i < aliases.length; i++) {
if (!dest[aliases[i].n]) {
const m = resolve(fragment, aliases[i].x);
dest[aliases[i].n] = m;
m.reference();
}
}

return dest;
}

export default class Fragment {
constructor(options) {
Expand Down Expand Up @@ -46,6 +59,14 @@ export default class Fragment {

bind(context) {
this.context = context;

if (this.owner.template.z) {
this.aliases = resolveAliases(
this.owner.template.z,
this.owner.containerFragment || this.parent
);
}

const len = this.items.length;
for (let i = 0; i < len; i++) this.items[i].bind();
this.bound = true;
Expand Down Expand Up @@ -207,6 +228,19 @@ export default class Fragment {
}

rebound(update) {
if (this.owner.template.z) {
const aliases = this.aliases;
for (const k in aliases) {
if (aliases[k].rebound) aliases[k].rebound(update);
else {
aliases[k].unreference();
aliases[k] = 0;
}
}

resolveAliases(this.owner.template.z, this.owner.containerFragment || this.parent, aliases);
}

this.items.forEach(x => x.rebound(update));
if (update) {
if (this.rootModel) this.rootModel.applyValue(this.context.getKeypath(this.ractive.root));
Expand Down Expand Up @@ -268,6 +302,14 @@ export default class Fragment {
}

unbind(view) {
if (this.owner.template.z && !this.owner.yielder) {
for (const k in this.aliases) {
this.aliases[k].unreference();
}

this.aliases = {};
}

this.context = null;
const len = this.items.length;
for (let i = 0; i < len; i++) this.items[i].unbind(view);
Expand Down
74 changes: 0 additions & 74 deletions src/view/items/Alias.js

This file was deleted.

25 changes: 2 additions & 23 deletions src/view/items/Partial.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import noop from 'utils/noop';
import { MustacheContainer } from './shared/Mustache';
import Fragment from '../Fragment';
import getPartialTemplate from './partial/getPartialTemplate';
import { resolveAliases } from './Alias';
import { warnOnceIfDebug, warnIfDebug } from 'utils/log';
import parser from 'src/Ractive/config/runtime-parser';
import runloop from 'src/global/runloop';
Expand Down Expand Up @@ -114,19 +113,6 @@ assign(proto, {
},

rebound(update) {
const aliases = this.fragment && this.fragment.aliases;
if (aliases) {
for (const k in aliases) {
if (aliases[k].rebound) aliases[k].rebound(update);
else {
aliases[k].unreference();
aliases[k] = 0;
}
}
if (this.template.z) {
resolveAliases(this.template.z, this.containerFragment || this.up, aliases);
}
}
if (this._attrs) {
keys(this._attrs).forEach(k => this._attrs[k].rebound(update));
}
Expand Down Expand Up @@ -186,8 +172,6 @@ assign(proto, {
unbind(view) {
this.fragment.unbind(view);

this.fragment.aliases = null;

this.unbindAttrs(view);

MustacheContainer.prototype.unbind.call(this, view);
Expand Down Expand Up @@ -247,17 +231,12 @@ function createFragment(self, partial) {

if (self.fn) options.cssIds = self.fn._cssIds;

const fragment = (self.fragment = new Fragment(options));

// partials may have aliases that need to be in place before binding
if (self.template.z) {
fragment.aliases = resolveAliases(self.template.z, self.containerFragment || self.up);
}
self.fragment = new Fragment(options);
}

function contextifyTemplate(self) {
if (self.template.c) {
self.partial = [{ t: SECTION, n: SECTION_WITH, f: self.partial }];
self.partial = [{ t: SECTION, n: SECTION_WITH, f: self.partial, z: self.template.z }];
assign(self.partial[0], self.template.c);
if (self.yielder) self.partial[0].y = self;
}
Expand Down
12 changes: 8 additions & 4 deletions src/view/items/Section.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
ALIAS,
SECTION_EACH,
SECTION_IF,
SECTION_IF_WITH,
Expand Down Expand Up @@ -34,7 +35,8 @@ export default class Section extends MustacheContainer {
constructor(options) {
super(options);

this.sectionType = options.template.n || null;
this.isAlias = options.template.t === ALIAS;
this.sectionType = options.template.n || (this.isAlias && SECTION_WITH) || null;
this.templateSectionType = this.sectionType;
this.subordinate = options.template.l === 1;
this.fragment = null;
Expand All @@ -49,7 +51,7 @@ export default class Section extends MustacheContainer {
}

// if we managed to bind, we need to create children
if (this.model) {
if (this.model || this.isAlias) {
this.dirty = true;
this.update();
} else if (
Expand Down Expand Up @@ -138,7 +140,7 @@ export default class Section extends MustacheContainer {
this.fragment.context = this.model;
}

if (!this.model && this.sectionType !== SECTION_UNLESS) return;
if (!this.model && this.sectionType !== SECTION_UNLESS && !this.isAlias) return;

this.dirty = false;

Expand Down Expand Up @@ -173,7 +175,9 @@ export default class Section extends MustacheContainer {
const fragmentShouldExist =
this.sectionType === SECTION_EACH || // each always gets a fragment, which may have no iterations
this.sectionType === SECTION_WITH || // with (partial context) always gets a fragment
(siblingFalsey && (this.sectionType === SECTION_UNLESS ? !this.isTruthy() : this.isTruthy())); // if, unless, and if-with depend on siblings and the condition
(siblingFalsey &&
(this.sectionType === SECTION_UNLESS ? !this.isTruthy() : this.isTruthy())) || // if, unless, and if-with depend on siblings and the condition
this.isAlias;

if (fragmentShouldExist) {
if (!this.fragment) this.fragment = this.detached;
Expand Down
3 changes: 1 addition & 2 deletions src/view/items/createItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
YIELDER
} from 'config/types';
import { ATTRIBUTE, BINDING_FLAG, DECORATOR, EVENT, TRANSITION } from 'config/types';
import Alias from './Alias';
import Attribute from './element/Attribute';
import BindingFlag from './element/BindingFlag';
import Comment from './Comment';
Expand Down Expand Up @@ -42,7 +41,7 @@ import Await from './Await';
import { isString, isFunction } from 'utils/is';

const constructors = {};
constructors[ALIAS] = Alias;
constructors[ALIAS] = Section;
constructors[ANCHOR] = Component;
constructors[AWAIT] = Await;
constructors[DOCTYPE] = Doctype;
Expand Down
1 change: 0 additions & 1 deletion src/view/resolvers/resolveReference.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ export default function resolveReference(fragment, ref) {
if (context) {
if (context.context) {
context = context.context;
if (context.has(base)) return context.joinKey(base).joinAll(keys);
} else {
// alias block, so get next full context for later
context = fragment.findContext();
Expand Down
17 changes: 17 additions & 0 deletions tests/browser/partials.js
Original file line number Diff line number Diff line change
Expand Up @@ -1280,4 +1280,21 @@ export default function() {

t.htmlEqual(fixture.innerHTML, '5');
});

test(`partial with context and aliases`, t => {
new Ractive({
target: fixture,
template: `{{#with foo}}{{>bar baz, 42 as foo}}{{/with}}`,
partials: {
bar: `{{.foo}} {{foo}}`
},
data: {
foo: {
baz: { foo: 99 }
}
}
});

t.htmlEqual(fixture.innerHTML, '99 42');
});
}

0 comments on commit cb374fc

Please sign in to comment.