Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUGFIX beta] Change style deprecation to warning. #10711

Merged
merged 1 commit into from
Mar 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 48 additions & 20 deletions packages/ember-htmlbars/tests/attr_nodes/style_test.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,78 @@
/* globals EmberDev */

import Ember from "ember-metal/core";
import EmberView from "ember-views/views/view";
import compile from "ember-template-compiler/system/compile";
import { SafeString } from "ember-htmlbars/utils/string";
import { runAppend, runDestroy } from "ember-runtime/tests/utils";
import { styleWarning } from "ember-views/attr_nodes/attr_node";

var view;
var view, originalWarn, warnings;

QUnit.module("ember-htmlbars: style attribute", {
setup() {
warnings = [];
originalWarn = Ember.warn;
Ember.warn = function(message, test) {
if (!test) {
warnings.push(message);
}
};
},

teardown() {
runDestroy(view);
Ember.warn = originalWarn;
}
});

if (Ember.FEATURES.isEnabled('ember-htmlbars-attribute-syntax')) {
// jscs:disable validateIndentation

QUnit.test('specifying `<div style="width: {{userValue}}></div>` is [DEPRECATED]', function() {
view = EmberView.create({
userValue: '42',
template: compile('<div style="width: {{view.userValue}}"></div>')
});
if (!EmberDev.runningProdBuild) {
QUnit.test('specifying `<div style={{userValue}}></div>` generates a warning', function() {
view = EmberView.create({
userValue: 'width: 42px',
template: compile('<div style={{view.userValue}}></div>')
});

expectDeprecation(function() {
runAppend(view);
}, /Dynamic content in the `style` attribute is not escaped and may pose a security risk. Please perform a security audit and once verified change from `<div style="foo: {{property}}">` to `<div style="foo: {{{property}}}">/);
});

QUnit.test('specifying `<div style="width: {{{userValue}}}></div>` works properly', function() {
view = EmberView.create({
userValue: '42',
template: compile('<div style="width: {{view.userValue}}"></div>')
deepEqual(warnings, [styleWarning]);
});

expectNoDeprecation(function() {
QUnit.test('specifying `attributeBindings: ["style"]` generates a warning', function() {
view = EmberView.create({
userValue: 'width: 42px',
template: compile('<div style={{view.userValue}}></div>')
});

runAppend(view);

deepEqual(warnings, [styleWarning]);
});
});
}

QUnit.test('specifying `<div style="width: {{userValue}}></div>` works properly with a SafeString', function() {
QUnit.test('specifying `<div style={{{userValue}}}></div>` works properly without a warning', function() {
view = EmberView.create({
userValue: new SafeString('42'),
template: compile('<div style="width: {{view.userValue}}"></div>')
userValue: 'width: 42px',
template: compile('<div style={{{view.userValue}}}></div>')
});

expectNoDeprecation(function() {
runAppend(view);
runAppend(view);

deepEqual(warnings, [ ]);
});

QUnit.test('specifying `<div style={{userValue}}></div>` works properly with a SafeString', function() {
view = EmberView.create({
userValue: new SafeString('width: 42px'),
template: compile('<div style={{view.userValue}}></div>')
});

runAppend(view);

deepEqual(warnings, [ ]);
});

// jscs:enable validateIndentation
Expand Down
46 changes: 31 additions & 15 deletions packages/ember-htmlbars/tests/helpers/bind_attr_test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/*globals EmberDev */
/*jshint newcap:false*/

import Ember from "ember-metal/core"; // Ember.lookup
import run from "ember-metal/run_loop";
import Namespace from "ember-runtime/system/namespace";
Expand All @@ -11,13 +13,15 @@ import { observersFor } from "ember-metal/observer";
import { Registry } from "ember-runtime/system/container";
import { set } from "ember-metal/property_set";
import { runAppend, runDestroy } from "ember-runtime/tests/utils";
import { styleWarning } from "ember-views/attr_nodes/attr_node";
import { SafeString } from "ember-htmlbars/utils/string";

import helpers from "ember-htmlbars/helpers";
import compile from "ember-template-compiler/system/compile";
var view;

var originalLookup = Ember.lookup;
var TemplateTests, registry, container, lookup;
var TemplateTests, registry, container, lookup, warnings, originalWarn;

/**
This module specifically tests integration with Handlebars and Ember-specific
Expand All @@ -35,6 +39,14 @@ QUnit.module("ember-htmlbars: {{bind-attr}}", {
registry.optionsForType('template', { instantiate: false });
registry.register('view:default', _MetamorphView);
registry.register('view:toplevel', EmberView.extend());

warnings = [];
originalWarn = Ember.warn;
Ember.warn = function(message, test) {
if (!test) {
warnings.push(message);
}
};
},

teardown() {
Expand All @@ -43,6 +55,7 @@ QUnit.module("ember-htmlbars: {{bind-attr}}", {
registry = container = view = null;

Ember.lookup = lookup = originalLookup;
Ember.warn = originalWarn;
TemplateTests = null;
}
});
Expand Down Expand Up @@ -600,24 +613,27 @@ QUnit.test("src attribute bound to null is not present", function() {
ok(!view.element.firstChild.hasAttribute('src'), "src attribute not present");
});

QUnit.test('specifying `<div {{bind-attr style=userValue}}></div>` is [DEPRECATED]', function() {
view = EmberView.create({
userValue: '42',
template: compile('<div {{bind-attr style=view.userValue}}></div>')
});
if (!EmberDev.runningProdBuild) {

QUnit.test('specifying `<div {{bind-attr style=userValue}}></div>` triggers a warning', function() {
view = EmberView.create({
userValue: '42',
template: compile('<div {{bind-attr style=view.userValue}}></div>')
});

expectDeprecation(function() {
runAppend(view);
}, /Dynamic content in the `style` attribute is not escaped and may pose a security risk. Please perform a security audit and once verified change from `<div {{bind-attr style=someProperty}}>` to `<div style={{{someProperty}}}>/);
});

QUnit.test('specifying `<div {{{bind-attr style=userValue}}}></div>` works properly', function() {
view = EmberView.create({
userValue: '42',
template: compile('<div {{{bind-attr style=view.userValue}}}></div>')
deepEqual(warnings, [styleWarning]);
});
}

expectNoDeprecation(function() {
runAppend(view);
QUnit.test('specifying `<div {{bind-attr style=userValue}}></div>` works properly with a SafeString', function() {
view = EmberView.create({
userValue: new SafeString('42'),
template: compile('<div {{bind-attr style=view.userValue}}></div>')
});

runAppend(view);

deepEqual(warnings, [ ]);
});
20 changes: 13 additions & 7 deletions packages/ember-views/lib/attr_nodes/attr_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export default function AttrNode(attrName, attrValue) {
this.init(attrName, attrValue);
}

export var styleWarning = 'Binding style attributes may introduce cross-site scripting vulnerabilities; ' +
'please ensure that values being bound are properly escaped. For more information, ' +
'including how to disable this warning, see ' +
'http://emberjs.com/deprecations/v1.x/#toc_warning-when-binding-style-attributes.';

AttrNode.prototype.init = function init(attrName, simpleAttrValue) {
this.isView = true;

Expand All @@ -27,8 +32,6 @@ AttrNode.prototype.init = function init(attrName, simpleAttrValue) {
this.isDestroying = false;
this.lastValue = null;
this.hasRenderedInitially = false;
this._dynamicStyleDeprecationMessage = '`<div style="foo: {{property}}">` to ' +
'`<div style="foo: {{{property}}}">`.';

subscribe(this.attrValue, this.rerender, this);
};
Expand Down Expand Up @@ -76,16 +79,19 @@ AttrNode.prototype.render = function render(buffer) {
};

AttrNode.prototype._deprecateEscapedStyle = function AttrNode_deprecateEscapedStyle(value) {
Ember.deprecate(
'Dynamic content in the `style` attribute is not escaped and may pose a security risk. ' +
'Please perform a security audit and once verified change from ' +
this._dynamicStyleDeprecationMessage,
Ember.warn(
styleWarning,
(function(name, value, escaped) {
// SafeString
if (value && value.toHTML) {
return true;
}
return name !== 'style' || !escaped;

if (name !== 'style') {
return true;
}

return !escaped;
}(this.attrName, value, this._morph.escaped))
);
};
Expand Down
5 changes: 1 addition & 4 deletions packages/ember-views/lib/attr_nodes/legacy_bind.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ import o_create from "ember-metal/platform/create";

function LegacyBindAttrNode(attrName, attrValue) {
this.init(attrName, attrValue);

this._dynamicStyleDeprecationMessage = '`<div {{bind-attr style=someProperty}}>` to ' +
'`<div style={{{someProperty}}}>`.';
}

LegacyBindAttrNode.prototype = o_create(AttrNode.prototype);
Expand All @@ -34,7 +31,7 @@ LegacyBindAttrNode.prototype.render = function render(buffer) {
}

Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [value]),
value === null || value === undefined || typeOf(value) === 'number' || typeOf(value) === 'string' || typeOf(value) === 'boolean');
value === null || value === undefined || typeOf(value) === 'number' || typeOf(value) === 'string' || typeOf(value) === 'boolean' || !!(value && value.toHTML));

if (this.lastValue !== null || value !== null) {
this._deprecateEscapedStyle(value);
Expand Down