From bf878dbc0e60488890777bc48a7a3825957bb216 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sun, 10 Apr 2016 11:39:35 -0400 Subject: [PATCH 1/2] [BUGFIX beta] Use a symbol to detect if an object is a stream. Previously, having an `isStream` property on a component would cause us to assume that component was itself a stream. Using an internal symbol allows us to avoid reserving the property `isStream`. --- packages/ember-metal/lib/streams/stream.js | 7 +++++-- packages/ember-metal/lib/streams/utils.js | 11 ++++++----- packages/ember-metal/tests/streams/concat_test.js | 5 +++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/ember-metal/lib/streams/stream.js b/packages/ember-metal/lib/streams/stream.js index 902a156c8d3..814c65585ab 100644 --- a/packages/ember-metal/lib/streams/stream.js +++ b/packages/ember-metal/lib/streams/stream.js @@ -8,6 +8,10 @@ import Subscriber from 'ember-metal/streams/subscriber'; import Dependency from 'ember-metal/streams/dependency'; import { GUID_KEY } from 'ember-metal/utils'; import require from 'require'; +import symbol from 'ember-metal/symbol'; + +export const IS_STREAM = symbol('IS_STREAM'); + /** @module ember-metal */ @@ -26,9 +30,8 @@ var KeyStream; var ProxyMixin; BasicStream.prototype = { - isStream: true, - _init(label) { + this[IS_STREAM] = true; this.label = makeLabel(label); this.isActive = false; this.isDirty = true; diff --git a/packages/ember-metal/lib/streams/utils.js b/packages/ember-metal/lib/streams/utils.js index ff65e4a3496..710351d6d3c 100644 --- a/packages/ember-metal/lib/streams/utils.js +++ b/packages/ember-metal/lib/streams/utils.js @@ -1,5 +1,6 @@ import { assert } from 'ember-metal/debug'; import BasicStream, { Stream } from './stream'; +import { IS_STREAM } from 'ember-metal/streams/stream'; /* Check whether an object is a stream or not. @@ -11,7 +12,7 @@ import BasicStream, { Stream } from './stream'; @return {Boolean} `true` if the object is a stream, `false` otherwise. */ export function isStream(object) { - return object && object.isStream; + return object && object[IS_STREAM]; } /* @@ -27,7 +28,7 @@ export function isStream(object) { is provided. */ export function subscribe(object, callback, context) { - if (object && object.isStream) { + if (object && object[IS_STREAM]) { return object.subscribe(callback, context); } } @@ -44,7 +45,7 @@ export function subscribe(object, callback, context) { @param {Object} [context] Object originally passed to `subscribe()`. */ export function unsubscribe(object, callback, context) { - if (object && object.isStream) { + if (object && object[IS_STREAM]) { object.unsubscribe(callback, context); } } @@ -60,7 +61,7 @@ export function unsubscribe(object, callback, context) { @return The stream's current value, or the non-stream object itself. */ export function read(object) { - if (object && object.isStream) { + if (object && object[IS_STREAM]) { return object.value(); } else { return object; @@ -343,7 +344,7 @@ export function chain(value, fn, label) { } export function setValue(object, value) { - if (object && object.isStream) { + if (object && object[IS_STREAM]) { object.setValue(value); } } diff --git a/packages/ember-metal/tests/streams/concat_test.js b/packages/ember-metal/tests/streams/concat_test.js index 4aa985a2f27..67db9a9abda 100644 --- a/packages/ember-metal/tests/streams/concat_test.js +++ b/packages/ember-metal/tests/streams/concat_test.js @@ -1,7 +1,8 @@ import { Stream } from 'ember-metal/streams/stream'; import { concat, - read + read, + isStream } from 'ember-metal/streams/utils'; @@ -28,7 +29,7 @@ QUnit.test('returns a stream if a stream is in the array', function(assert) { }); let result = concat(['foo', stream, 'baz'], ' '); - assert.ok(result.isStream, 'a stream is returned'); + assert.ok(isStream(result), 'a stream is returned'); assert.equal(read(result), 'foo bar baz'); }); From 08e7df46b159db7339c77c5fec78ce9769168401 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Sun, 10 Apr 2016 11:52:23 -0400 Subject: [PATCH 2/2] Add regression test for using `isStream` property on a component. --- .../components/curly-components-test.js | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/packages/ember-glimmer/tests/integration/components/curly-components-test.js b/packages/ember-glimmer/tests/integration/components/curly-components-test.js index 3af67603d43..98538837bfa 100644 --- a/packages/ember-glimmer/tests/integration/components/curly-components-test.js +++ b/packages/ember-glimmer/tests/integration/components/curly-components-test.js @@ -917,4 +917,43 @@ moduleFor('Components test: curly components', class extends RenderingTest { this.assertElement(this.firstChild.childNodes[2], { tagName: 'b', content: 'bold' }); } + ['@test can use isStream property without conflict (#13271)']() { + let component; + let FooBarComponent = Component.extend({ + isStream: true, + + init() { + this._super(...arguments); + component = this; + } + }); + + this.registerComponent('foo-bar', { + ComponentClass: FooBarComponent, + + template: strip` + {{#if isStream}} + true + {{else}} + false + {{/if}} + ` + }); + + this.render('{{foo-bar}}'); + + this.assertComponentElement(this.firstChild, { content: 'true' }); + + this.runTask(() => this.rerender()); + + this.assertComponentElement(this.firstChild, { content: 'true' }); + + this.runTask(() => set(component, 'isStream', false)); + + this.assertComponentElement(this.firstChild, { content: 'false' }); + + this.runTask(() => set(component, 'isStream', true)); + + this.assertComponentElement(this.firstChild, { content: 'true' }); + } });