Skip to content

Commit

Permalink
fix(engine): render() can only return qualifying templates (#764)
Browse files Browse the repository at this point in the history
* fix(engine): render() can only return qualifying templates

* chore: remove unneeded return statement
  • Loading branch information
caridy authored and diervo committed Nov 5, 2018
1 parent d2942fc commit c6556de
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { compileTemplate } from 'test-utils';
import { createElement, LightningElement } from '../main';

const emptyTemplate = compileTemplate(`<template></template>`);

describe('class-list', () => {
describe('integration', () => {
it('should support static class attribute', () => {
Expand Down Expand Up @@ -237,6 +239,7 @@ describe('class-list', () => {
}
render() {
this.state.x;
return emptyTemplate;
}
}
MyComponent.publicMethods = ['initClassNames', 'updateTracked', 'addAnotherClass', 'addOtherClass'];
Expand Down
11 changes: 8 additions & 3 deletions packages/lwc-engine/src/framework/__tests__/invoker.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { compileTemplate } from 'test-utils';
import { createElement, LightningElement } from '../main';

const emptyTemplate = compileTemplate(`<template></template>`);

describe('invoker', () => {

describe('integration', () => {
Expand All @@ -9,7 +11,7 @@ describe('invoker', () => {
document.body.innerHTML = '';
});

it('should support undefined result from render()', () => {
it('should throw if render() returns undefined', () => {
let counter = 0;
class MyComponent extends LightningElement {
render() {
Expand All @@ -18,11 +20,13 @@ describe('invoker', () => {
}
}
const elm = createElement('x-foo', { is: MyComponent });
document.body.appendChild(elm);
expect(() => {
document.body.appendChild(elm);
}).toThrow();
expect(counter).toBe(1);
});

it('should throw if render() returns something that is not a function or a promise or undefined', () => {
it('should throw if render() returns something that is not a template function', () => {
class MyComponent extends LightningElement {
render() {
return 1;
Expand Down Expand Up @@ -246,6 +250,7 @@ describe('invoker', () => {
}
render() {
lifecycle.push('render');
return emptyTemplate;
}
}

Expand Down
5 changes: 5 additions & 0 deletions packages/lwc-engine/src/framework/__tests__/patch.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { compileTemplate } from 'test-utils';
import { createElement, LightningElement } from '../main';

const emptyTemplate = compileTemplate(`<template></template>`);

describe('patch', () => {

describe('#patch()', () => {
Expand Down Expand Up @@ -55,6 +57,7 @@ describe('patch', () => {
}
render() {
calls.push('child:render');
return emptyTemplate;
}
renderedCallback() {
calls.push('child:renderedCallback');
Expand Down Expand Up @@ -113,6 +116,7 @@ describe('patch', () => {
}
render() {
calls.push('child:render');
return emptyTemplate;
}
renderedCallback() {
calls.push('child:renderedCallback');
Expand Down Expand Up @@ -190,6 +194,7 @@ describe('patch', () => {
}
render() {
calls.push('child:render');
return emptyTemplate;
}
renderedCallback() {
calls.push('child:renderedCallback');
Expand Down
3 changes: 3 additions & 0 deletions packages/lwc-engine/src/framework/__tests__/vm.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { createElement, LightningElement } from '../main';
import { ViewModelReflection } from "../utils";
import { getErrorComponentStack, isNodeFromTemplate } from "../vm";

const emptyTemplate = compileTemplate(`<template></template>`);

describe('vm', () => {
describe('#isNodeFromTemplate', () => {
it('should return false when element is created externally', () => {
Expand Down Expand Up @@ -104,6 +106,7 @@ describe('vm', () => {
}
render() {
counter++;
return emptyTemplate;
}
}

Expand Down
8 changes: 8 additions & 0 deletions packages/lwc-engine/src/framework/__tests__/watcher.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { compileTemplate } from 'test-utils';
import { createElement, LightningElement } from '../main';

const emptyTemplate = compileTemplate(`<template></template>`);

describe('watcher', () => {

describe('integration', () => {
Expand All @@ -10,6 +12,7 @@ describe('watcher', () => {
class MyComponent1 extends LightningElement {
render() {
counter++;
return emptyTemplate;
}
}
const elm = createElement('x-foo', { is: MyComponent1 });
Expand Down Expand Up @@ -47,6 +50,7 @@ describe('watcher', () => {
class MyComponent3 extends LightningElement {
render() {
counter++;
return emptyTemplate;
}
}
MyComponent3.publicProps = { x: 1 };
Expand Down Expand Up @@ -147,6 +151,7 @@ describe('watcher', () => {
}
render() {
counter++;
return emptyTemplate;
}
}

Expand Down Expand Up @@ -265,6 +270,7 @@ describe('watcher', () => {
render() {
counter++;
this.state.list.map((v) => v + 1);
return emptyTemplate;
}
}
MyComponent1.track = { state: 1 };
Expand All @@ -291,6 +297,7 @@ describe('watcher', () => {
render() {
counter++;
this.state.list.map((v) => v + 1);
return emptyTemplate;
}
}
MyComponent1.publicMethods = ['popFromList'];
Expand All @@ -315,6 +322,7 @@ describe('watcher', () => {
render() {
counter++;
this.state.list.map((v) => v + 1);
return emptyTemplate;
}
}
MyComponent1.publicMethods = ['unshiftFromList'];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { compileTemplate } from 'test-utils';
import { createElement, LightningElement } from '../../main';

const emptyTemplate = compileTemplate(`<template></template>`);

describe('decorators/api.ts', () => {
describe('@api x', () => {
it('should allow inheriting public props', function() {
Expand Down Expand Up @@ -50,6 +52,7 @@ describe('decorators/api.ts', () => {
class MyComponent extends LightningElement {
render() {
counter++;
return emptyTemplate;
}
}
MyComponent.publicProps = {
Expand All @@ -74,6 +77,7 @@ describe('decorators/api.ts', () => {
render() {
this.x;
counter++;
return emptyTemplate;
}
}
MyComponent.publicProps = {
Expand Down Expand Up @@ -178,6 +182,7 @@ describe('decorators/api.ts', () => {
render() {
this.x;
counter++;
return emptyTemplate;
}
}
MyComponent.publicProps = {
Expand Down Expand Up @@ -209,6 +214,7 @@ describe('decorators/api.ts', () => {
render() {
this.x;
counter++;
return emptyTemplate;
}
}
MyComponent.publicProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { compileTemplate } from 'test-utils';
import { createElement, LightningElement } from '../../main';
import track from "../track";
import readonly from "../readonly";

const emptyTemplate = compileTemplate(`<template></template>`);

describe('track.ts', () => {
describe('integration', () => {
it('should support setting a tracked property in constructor', () => {
Expand Down Expand Up @@ -56,6 +59,7 @@ describe('track.ts', () => {
render() {
counter++;
this.foo.x;
return emptyTemplate;
}
}
MyComponent.track = { foo: 1 };
Expand All @@ -81,6 +85,7 @@ describe('track.ts', () => {
render() {
counter++;
this.foo.x;
return emptyTemplate;
}
}
MyComponent.track = { foo: 1 };
Expand Down Expand Up @@ -194,6 +199,7 @@ describe('track.ts', () => {
class MyComponent extends LightningElement {
render() {
this.foo = 1;
return emptyTemplate;
}
}
MyComponent.track = { foo: { } };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { compileTemplate } from 'test-utils';
import { createElement, LightningElement } from '../../main';
import wire from "../wire";

const emptyTemplate = compileTemplate(`<template></template>`);

describe('wire.ts', () => {
describe('integration', () => {
it('should support setting a wired property in constructor', () => {
Expand Down Expand Up @@ -55,6 +58,7 @@ describe('wire.ts', () => {
render() {
counter++;
this.foo.x;
return emptyTemplate;
}
}
MyComponent.wire = { foo: {} };
Expand Down Expand Up @@ -82,6 +86,7 @@ describe('wire.ts', () => {
render() {
counter++;
this.foo.x;
return emptyTemplate;
}
}
MyComponent.wire = { foo: {} };
Expand Down Expand Up @@ -197,6 +202,7 @@ describe('wire.ts', () => {
class MyComponent extends LightningElement {
render() {
this.foo = 1;
return emptyTemplate;
}
}
MyComponent.wire = { foo: { } };
Expand Down
9 changes: 3 additions & 6 deletions packages/lwc-engine/src/framework/invoker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,10 @@ export function invokeComponentRenderMethod(vm: VM): VNodes {

try {
const html = callHook(component, render);
if (isFunction(html)) {
result = evaluateTemplate(vm, html);
} else if (!isUndefined(html)) {
if (process.env.NODE_ENV !== 'production') {
assert.fail(`The template rendered by ${vm} must return an imported template tag (e.g.: \`import html from "./${vm.def.name}.html"\`) or undefined, instead, it has returned ${html}.`);
}
if (process.env.NODE_ENV !== 'production') {
assert.isTrue(isFunction(html), `The template rendered by ${vm} must return an imported template tag (e.g.: \`import html from "./${vm.def.name}.html"\`), instead, it has returned ${html}.`);
}
result = evaluateTemplate(vm, html);
} catch (e) {
error = Object(e);
} finally {
Expand Down
8 changes: 3 additions & 5 deletions packages/lwc-engine/src/framework/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,9 @@ export function evaluateTemplate(vm: VM, html: Template): Array<VNode|null> {
const { component, context, cmpSlots, cmpTemplate } = vm;
// reset the cache memoizer for template when needed
if (html !== cmpTemplate) {
if (!isUndefined(cmpTemplate)) {
// It is important to reset the content to avoid reusing similar elements generated from a different
// template, because they could have similar IDs, and snabbdom just rely on the IDs.
resetShadowRoot(vm);
}
// It is important to reset the content to avoid reusing similar elements generated from a different
// template, because they could have similar IDs, and snabbdom just rely on the IDs.
resetShadowRoot(vm);

// Check that the template was built by the compiler
if (!isTemplateRegistered(html)) {
Expand Down

0 comments on commit c6556de

Please sign in to comment.