=>
directive((part: NodePart): void => {
+ if (part._previousValue === value && _isPrimitiveValue(value)) {
+ return;
+ }
const tmp = document.createElement('template');
tmp.innerHTML = value;
part.setValue(document.importNode(tmp.content, true));
+ part._previousValue = value;
});
diff --git a/src/lit-html.ts b/src/lit-html.ts
index a74f76124f..7626da35ad 100644
--- a/src/lit-html.ts
+++ b/src/lit-html.ts
@@ -468,7 +468,7 @@ export const noChange = {};
*/
export { noChange as directiveValue };
-const isPrimitiveValue = (value: any) => value === null ||
+export const _isPrimitiveValue = (value: any) => value === null ||
!(typeof value === 'object' || typeof value === 'function');
export interface Part {
@@ -531,7 +531,7 @@ export class AttributePart implements MultiPart {
}
for (let i = startIndex; i < startIndex + this.size; i++) {
if (this._previousValues[i] !== values[i] ||
- !isPrimitiveValue(values[i])) {
+ !_isPrimitiveValue(values[i])) {
return false;
}
}
@@ -579,7 +579,7 @@ export class NodePart implements SinglePart {
if (value === noChange) {
return;
}
- if (isPrimitiveValue(value)) {
+ if (_isPrimitiveValue(value)) {
// Handle primitive values
// If the value didn't change, do nothing
if (value === this._previousValue) {
diff --git a/src/test/lib/unsafe-html_test.ts b/src/test/lib/unsafe-html_test.ts
index dd65ab163f..05c668dcf8 100644
--- a/src/test/lib/unsafe-html_test.ts
+++ b/src/test/lib/unsafe-html_test.ts
@@ -24,8 +24,13 @@ const assert = chai.assert;
suite('unsafeHTML', () => {
+ let container: HTMLElement;
+
+ setup(() => {
+ container = document.createElement('div');
+ });
+
test('renders HTML', () => {
- const container = document.createElement('div');
render(
html`before${unsafeHTML('innerafter
')}`,
container);
@@ -33,4 +38,41 @@ suite('unsafeHTML', () => {
stripExpressionDelimeters(container.innerHTML), 'beforeinnerafter
');
});
+ test('dirty checks primitive values', () => {
+ const value = 'aaa';
+ const t = () => html`${unsafeHTML(value)}
`;
+
+ // Initial render
+ render(t(), container);
+ assert.equal(stripExpressionDelimeters(container.innerHTML), 'aaa
');
+
+ // Modify instance directly. Since lit-html doesn't dirty check against
+ // actual DOM, but again previous part values, this modification should
+ // persist through the next render if dirty checking works.
+ const text = container.firstChild!.childNodes[1] as Text;
+ text.textContent = 'bbb';
+ assert.equal(stripExpressionDelimeters(container.innerHTML), 'bbb
');
+
+ // Re-render with the same value
+ render(t(), container);
+
+ assert.equal(stripExpressionDelimeters(container.innerHTML), 'bbb
');
+ const text2 = container.firstChild!.childNodes[1] as Text;
+ assert.strictEqual(text, text2);
+ });
+
+ test('does not dirty check complex values', () => {
+ const value = ['aaa'];
+ const t = () => html`${unsafeHTML(value)}
`;
+
+ // Initial render
+ render(t(), container);
+ assert.equal(stripExpressionDelimeters(container.innerHTML), 'aaa
');
+
+ // Re-render with the same value, but a different deep property
+ value[0] = 'bbb';
+ render(t(), container);
+ assert.equal(stripExpressionDelimeters(container.innerHTML), 'bbb
');
+ });
+
});