Skip to content

Commit

Permalink
Hot Reload PoC
Browse files Browse the repository at this point in the history
Co-authored-by: Robert Jackson <me@rwjblue.com>
  • Loading branch information
chancancode and rwjblue committed Sep 24, 2018
1 parent aa83863 commit 76a1976
Showing 1 changed file with 172 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import { ENV } from '@ember/-internals/environment';
import Controller from '@ember/controller';
import Service, { inject as injectService } from '@ember/service';
import { moduleFor, ApplicationTest } from '../../utils/test-case';
import { strip } from '../../utils/abstract-test-case';
import { Route } from '@ember/-internals/routing';
import { Component } from '@ember/-internals/glimmer';
import { Component, Helper } from '@ember/-internals/glimmer';

moduleFor(
'Application test: rendering',
class extends ApplicationTest {
constructor() {
super(...arguments);
this._APPLICATION_TEMPLATE_WRAPPER = ENV._APPLICATION_TEMPLATE_WRAPPER;
this._TEMPLATE_ONLY_GLIMMER_COMPONENTS = ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS;
}

teardown() {
super.teardown();
ENV._APPLICATION_TEMPLATE_WRAPPER = this._APPLICATION_TEMPLATE_WRAPPER;
ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS = this._TEMPLATE_ONLY_GLIMMER_COMPONENTS;
}

['@test it can render the application template with a wrapper']() {
Expand Down Expand Up @@ -503,5 +506,173 @@ moduleFor(
}, expectedBacktrackingMessage);
});
}

['@test hot reload (without component class)']() {
ENV._APPLICATION_TEMPLATE_WRAPPER = false;
ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS = true;

let invalidate;

this.add(
'service:component-template-revisions',
Service.extend({
init() {
this._super(...arguments);
this.revisions = {};
this.listeners = [];

invalidate = componentName => {
let revision = this.revisions[componentName];

if (revision === undefined) {
revision = 0;
}

this.revisions[componentName] = ++revision;

this.listeners.forEach(callback => callback());
};
},

listen(callback) {
this.listeners.push(callback);
},

revisionFor(componentName) {
return this.revisions[componentName];
},
})
);

this.add(
'helper:revisioned-component-name',
Helper.extend({
revision: injectService('component-template-revisions'),

init() {
this._super(...arguments);
this.revision.listen(() => this.recompute());
},

compute([name]) {
let revision = this.revision.revisionFor(name);

if (revision === undefined) {
return name;
} else {
return `${name}--hot-reload-${revision}`;
}
},
})
);

this.addTemplate('application', `{{component (revisioned-component-name "foo-bar")}}`);

this.addComponent('foo-bar', {
ComponentClass: null,
template: '<h1>foo-bar</h1>',
});

return this.visit('/').then(() => {
this.assertInnerHTML('<h1>foo-bar</h1>');

this.runTask(() => {
this.addComponent('foo-bar--hot-reload-1', {
ComponentClass:
this.applicationInstance.resolveRegistration('component:foo-bar') || null,
template: '<h1>foo-bar (revision 1)</h1>',
});

invalidate('foo-bar');
});

this.assertInnerHTML('<h1>foo-bar (revision 1)</h1>');
});
}

['@test hot reload (with component class)']() {
ENV._APPLICATION_TEMPLATE_WRAPPER = false;

let invalidate;

this.add(
'service:component-template-revisions',
Service.extend({
init() {
this._super(...arguments);
this.revisions = {};
this.listeners = [];

invalidate = componentName => {
let revision = this.revisions[componentName];

if (revision === undefined) {
revision = 0;
}

this.revisions[componentName] = ++revision;

this.listeners.forEach(callback => callback());
};
},

listen(callback) {
this.listeners.push(callback);
},

revisionFor(componentName) {
return this.revisions[componentName];
},
})
);

this.add(
'helper:revisioned-component-name',
Helper.extend({
revision: injectService('component-template-revisions'),

init() {
this._super(...arguments);
this.revision.listen(() => this.recompute());
},

compute([name]) {
let revision = this.revision.revisionFor(name);

if (revision === undefined) {
return name;
} else {
return `${name}--hot-reload-${revision}`;
}
},
})
);

this.addTemplate('application', `{{component (revisioned-component-name "foo-bar")}}`);

this.addComponent('foo-bar', {
ComponentClass: Component.extend({
tagName: '',
name: 'foo-bar',
}),
template: '<h1>{{this.name}}</h1>',
});

return this.visit('/').then(() => {
this.assertInnerHTML('<h1>foo-bar</h1>');

this.runTask(() => {
this.addComponent('foo-bar--hot-reload-1', {
ComponentClass:
this.applicationInstance.resolveRegistration('component:foo-bar') || null,
template: '<h1>{{this.name}} (revision 1)</h1>',
});

invalidate('foo-bar');
});

this.assertInnerHTML('<h1>foo-bar (revision 1)</h1>');
});
}
}
);

0 comments on commit 76a1976

Please sign in to comment.