Skip to content

Commit 8be1a9d

Browse files
authored
Merge pull request #16227 from rondale-sc/utilize-rehydration-serialization-from-glimmer
Allow visit to specify Rehydration/Serialization or default ClientBuilder
2 parents af48b4e + 04ad41d commit 8be1a9d

File tree

5 files changed

+114
-10
lines changed

5 files changed

+114
-10
lines changed

packages/ember-application/lib/system/application-instance.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,15 @@ class BootOptions {
343343
*/
344344
this.isInteractive = environment.hasDOM; // This default is overridable below
345345

346+
347+
/**
348+
@property _renderMode
349+
@type string
350+
@default false
351+
@private
352+
*/
353+
this._renderMode = options._renderMode;
354+
346355
/**
347356
Run in a full browser environment.
348357
@@ -482,6 +491,7 @@ class BootOptions {
482491
// For compatibility with existing code
483492
env.hasDOM = this.isBrowser;
484493
env.isInteractive = this.isInteractive;
494+
env._renderMode = this._renderMode;
485495
env.options = this;
486496
return env;
487497
}

packages/ember-application/tests/system/visit_test.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Engine from '../../system/engine';
1212
import { Route } from 'ember-routing';
1313
import { Component, helper } from 'ember-glimmer';
1414
import { compile } from 'ember-template-compiler';
15+
import { ENV } from 'ember-environment';
1516

1617
function expectAsyncError() {
1718
RSVP.off('error');
@@ -21,6 +22,7 @@ moduleFor('Application - visit()', class extends ApplicationTestCase {
2122

2223
teardown() {
2324
RSVP.on('error', onerrorDefault);
25+
ENV._APPLICATION_TEMPLATE_WRAPPER = false;
2426
super.teardown();
2527
}
2628

@@ -35,6 +37,66 @@ moduleFor('Application - visit()', class extends ApplicationTestCase {
3537
);
3638
}
3739

40+
[`@test does not add serialize-mode markers by default`](assert) {
41+
let templateContent = '<div class="foo">Hi, Mom!</div>';
42+
this.addTemplate('index', templateContent);
43+
let rootElement = document.createElement('div');
44+
45+
let bootOptions = {
46+
isBrowser: false,
47+
rootElement
48+
};
49+
50+
ENV._APPLICATION_TEMPLATE_WRAPPER = false;
51+
return this.visit('/', bootOptions).then(()=> {
52+
assert.equal(rootElement.innerHTML, templateContent, 'without serialize flag renders as expected');
53+
});
54+
}
55+
56+
[`@test _renderMode: rehydration`](assert) {
57+
assert.expect(2);
58+
59+
let indexTemplate = '<div class="foo">Hi, Mom!</div>';
60+
this.addTemplate('index', indexTemplate);
61+
let rootElement = document.createElement('div');
62+
63+
let bootOptions = {
64+
isBrowser: false,
65+
rootElement,
66+
_renderMode: 'serialize'
67+
};
68+
69+
ENV._APPLICATION_TEMPLATE_WRAPPER = false;
70+
71+
return this.visit('/', bootOptions)
72+
.then((instance) => {
73+
assert.equal(
74+
instance.rootElement.firstChild.nodeValue,
75+
'%+b:0%',
76+
'glimmer-vm comment node was not found'
77+
);
78+
}).then(() =>{
79+
return this.runTask(()=>{
80+
this.applicationInstance.destroy();
81+
this.applicationInstance = null;
82+
});
83+
}).then(() => {
84+
bootOptions = {
85+
isBrowser: false,
86+
rootElement,
87+
_renderMode: 'rehydrate'
88+
};
89+
90+
this.application.visit('/', bootOptions).then(instance => {
91+
assert.equal(
92+
instance.rootElement.innerHTML,
93+
indexTemplate,
94+
'was not properly rehydrated'
95+
);
96+
});
97+
});
98+
}
99+
38100
// This tests whether the application is "autobooted" by registering an
39101
// instance initializer and asserting it never gets run. Since this is
40102
// inherently testing that async behavior *doesn't* happen, we set a

packages/ember-glimmer/lib/dom.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
///<reference path="./simple-dom.d.ts" />
2-
export { DOMChanges, DOMTreeConstruction } from '@glimmer/runtime';
3-
export { NodeDOMTreeConstruction } from '@glimmer/node';
2+
export {
3+
DOMChanges,
4+
DOMTreeConstruction,
5+
clientBuilder,
6+
rehydrationBuilder
7+
} from '@glimmer/runtime';
8+
export {
9+
NodeDOMTreeConstruction,
10+
serializeBuilder
11+
} from '@glimmer/node';

packages/ember-glimmer/lib/renderer.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import {
44
clientBuilder,
55
CurriedComponentDefinition,
66
curry,
7+
Cursor,
78
DynamicScope as GlimmerDynamicScope,
9+
ElementBuilder,
810
IteratorResult,
911
renderMain,
1012
RenderResult,
@@ -35,6 +37,7 @@ import { UnboundReference } from './utils/references';
3537
import OutletView from './views/outlet';
3638

3739
const { backburner } = run;
40+
export type IBuilder = (env: Environment, cursor: Cursor) => ElementBuilder;
3841

3942
export class DynamicScope implements GlimmerDynamicScope {
4043
constructor(
@@ -79,7 +82,9 @@ class RootState {
7982
template: OwnedTemplate,
8083
self: VersionedPathReference<Opaque>,
8184
parentElement: Simple.Element,
82-
dynamicScope: DynamicScope) {
85+
dynamicScope: DynamicScope,
86+
builder: IBuilder
87+
) {
8388
assert(`You cannot render \`${self.value()}\` without a template.`, template !== undefined);
8489

8590
this.id = getViewId(root);
@@ -100,7 +105,7 @@ class RootState {
100105
env,
101106
self,
102107
dynamicScope,
103-
clientBuilder(env, { element: parentElement, nextSibling: null}),
108+
builder(env, { element: parentElement, nextSibling: null }),
104109
handle
105110
);
106111
let iteratorResult: IteratorResult<RenderResult>;
@@ -249,8 +254,9 @@ export abstract class Renderer {
249254
private _lastRevision: number;
250255
private _isRenderingRoots: boolean;
251256
private _removedRoots: RootState[];
257+
private _builder: IBuilder;
252258

253-
constructor(env: Environment, rootTemplate: OwnedTemplate, _viewRegistry = fallbackViewRegistry, destinedForDOM = false) {
259+
constructor(env: Environment, rootTemplate: OwnedTemplate, _viewRegistry = fallbackViewRegistry, destinedForDOM = false, builder = clientBuilder) {
254260
this._env = env;
255261
this._rootTemplate = rootTemplate;
256262
this._viewRegistry = _viewRegistry;
@@ -260,6 +266,7 @@ export abstract class Renderer {
260266
this._lastRevision = -1;
261267
this._isRenderingRoots = false;
262268
this._removedRoots = [];
269+
this._builder = builder;
263270
}
264271

265272
// renderer HOOKS
@@ -280,7 +287,7 @@ export abstract class Renderer {
280287
target: Simple.Element) {
281288
let self = new UnboundReference(definition);
282289
let dynamicScope = new DynamicScope(null, UNDEFINED_REFERENCE);
283-
let rootState = new RootState(root, this._env, this._rootTemplate, self, target, dynamicScope);
290+
let rootState = new RootState(root, this._env, this._rootTemplate, self, target, dynamicScope, this._builder);
284291
this._renderRoot(rootState);
285292
}
286293

@@ -489,8 +496,8 @@ export abstract class Renderer {
489496
}
490497

491498
export class InertRenderer extends Renderer {
492-
static create({ env, rootTemplate, _viewRegistry }: {env: Environment, rootTemplate: OwnedTemplate, _viewRegistry: any}) {
493-
return new this(env, rootTemplate, _viewRegistry, false);
499+
static create({ env, rootTemplate, _viewRegistry, builder }: {env: Environment, rootTemplate: OwnedTemplate, _viewRegistry: any, builder: any}) {
500+
return new this(env, rootTemplate, _viewRegistry, false, builder);
494501
}
495502

496503
getElement(_view: Opaque): Simple.Element | undefined {
@@ -499,8 +506,8 @@ export class InertRenderer extends Renderer {
499506
}
500507

501508
export class InteractiveRenderer extends Renderer {
502-
static create({ env, rootTemplate, _viewRegistry }: {env: Environment, rootTemplate: OwnedTemplate, _viewRegistry: any}) {
503-
return new this(env, rootTemplate, _viewRegistry, true);
509+
static create({ env, rootTemplate, _viewRegistry, builder}: {env: Environment, rootTemplate: OwnedTemplate, _viewRegistry: any, builder: any}) {
510+
return new this(env, rootTemplate, _viewRegistry, true, builder);
504511
}
505512

506513
getElement(view: Opaque): Simple.Element | undefined {

packages/ember-glimmer/lib/setup-registry.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ import LinkToComponent from './components/link-to';
66
import TextArea from './components/text_area';
77
import TextField from './components/text_field';
88
import {
9+
clientBuilder,
910
DOMChanges,
1011
DOMTreeConstruction,
1112
NodeDOMTreeConstruction,
13+
rehydrationBuilder,
14+
serializeBuilder,
1215
} from './dom';
1316
import Environment from './environment';
1417
import loc from './helpers/loc';
@@ -29,6 +32,20 @@ export function setupApplicationRegistry(registry: Registry) {
2932
registry.injection('service:-glimmer-environment', 'appendOperations', 'service:-dom-tree-construction');
3033
registry.injection('renderer', 'env', 'service:-glimmer-environment');
3134

35+
registry.register('service:-dom-builder', {
36+
create({ bootOptions }: { bootOptions: { _renderMode: string } }) {
37+
let { _renderMode } = bootOptions;
38+
39+
switch(_renderMode) {
40+
case 'serialize': return serializeBuilder;
41+
case 'rehydrate': return rehydrationBuilder;
42+
default: return clientBuilder;
43+
}
44+
}
45+
});
46+
registry.injection('service:-dom-builder', 'bootOptions', '-environment:main');
47+
registry.injection('renderer', 'builder', 'service:-dom-builder');
48+
3249
registry.register(P`template:-root`, RootTemplate);
3350
registry.injection('renderer', 'rootTemplate', P`template:-root`);
3451

0 commit comments

Comments
 (0)