Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Remove angular.uppercase/lowercase #15445

Merged
merged 1 commit into from
Mar 8, 2017

Conversation

Narretz
Copy link
Contributor

@Narretz Narretz commented Nov 28, 2016

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
fix/refactor

What is the current behavior? (You can also link to an open issue here)
we expose lowercase/uppercase on the public angular object

Does this PR introduce a breaking change?
yes

Please check if the PR fulfills these requirements

Other information:

@Narretz Narretz added this to the 1.7.0 milestone Nov 28, 2016
@Narretz Narretz changed the title Fix remove upper lower Remove angular.uppercase/lowercase Nov 29, 2016
BREAKING CHANGE:

The helper functions `angular.lowercase` `and angular.uppercase` have
been removed.

These functions have been deprecated since 1.5.0. They are internally
used, but should not be exposed as it's possible that they do not
work correctly with all locales (e.g. Turkish). It makes more
sense that developers use special purpose functions if they need to.
mgol
mgol previously requested changes Feb 28, 2017
@@ -2072,13 +2072,13 @@ function MockXhr() {
var header = this.$$respHeaders[name];
if (header) return header;

name = angular.lowercase(name);
name = angular.$$lowercase(name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why keep the service, even as a private one? String.prototype methods should be enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed that angular.lowercase / uppercase is overwritten with a manual version that handles Turkish i:

angular.js/src/Angular.js

Lines 210 to 232 in 19bc521

var manualLowercase = function(s) {
/* eslint-disable no-bitwise */
return isString(s)
? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
: s;
/* eslint-enable */
};
var manualUppercase = function(s) {
/* eslint-disable no-bitwise */
return isString(s)
? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
: s;
/* eslint-enable */
};
// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
// with correct but slower alternatives. See https://github.com/angular/angular.js/issues/11387
if ('i' !== 'I'.toLowerCase()) {
lowercase = manualLowercase;
uppercase = manualUppercase;
}

So in core, we use a "safe" version. But we don't want anyone else to use it? I guess we don't want anyone to use the special version when usually the prototype functions are enough.

Copy link
Member

@mgol mgol Mar 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jQuery doesn't have any logic like that in its lowercasing and we haven't heard any complaints related to Turkish keyboards. Given jQuery's popularity I'd assume this code is no longer needed, especially that ES5 (!) mandates no such differences so I doubt any relatively recent browser would still have whatever issue existed (if it ever has).

I'd remove the "manual" functions as well. This is security-related code, though, so a this requires some consideration, though.

@petebacondarwin
Copy link
Contributor

LGTM - keeping the private methods for the time being.

@Narretz
Copy link
Contributor Author

Narretz commented Mar 8, 2017

K. FWIW, the "problem" still exists in modern browsers: http://plnkr.co/edit/cQHWgcqTLfZZ2LZXQQqG?p=preview
I can't really test toLocaleLowerCase correctly because the browser must be turkish ...

@Narretz Narretz dismissed mgol’s stale review March 8, 2017 12:51

Pete said to keep the private fns for now

@mgol
Copy link
Member

mgol commented Mar 8, 2017

@Narretz I don't see a problem in your fiddle. toLowerCase should always work in the same way so the Turkish lower "i" won't be the same as lowercased regular uppercase "I"; that seems expected.

@Narretz
Copy link
Contributor Author

Narretz commented Mar 8, 2017

Hm. So if we use regular lowercase, then theoretically there could be a case where we lowercase some developer / user provided value, which is then sent to a server and arrives "incorrectly" lower cased when compared to the expected lower case string on the server. I believe we do this to http headers, for example.

@Narretz Narretz merged commit 1daa4f2 into angular:master Mar 8, 2017
@mgol
Copy link
Member

mgol commented Mar 8, 2017

The manualLowercase function won't help in such a case either as it only lowercases Latin letters (from A to Z). This is, BTW, different from the native String#toLowerCase:
http://plnkr.co/edit/dZr9bnG8nIboMjwpgMpW?p=preview

So if there is any browser that violates ES5 and with Turkish locale has 'i' !== 'I'.toLowerCase() then we'll use a lowercasing function that doesn't convert lots of letters that we convert otherwise. Wouldn't it cause issues?

ellimist pushed a commit to ellimist/angular.js that referenced this pull request Mar 15, 2017
Closes angular#15445

BREAKING CHANGE:

The helper functions `angular.lowercase` `and angular.uppercase` have
been removed.

These functions have been deprecated since 1.5.0. They are internally
used, but should not be exposed as they contain special locale handling 
(for Turkish) to maintain internal consistency regardless of user-set locale.

Developers should generally use the built-ins `toLowerCase` and `toUpperCase`
or `toLocaleLowerCase` and `toLocaleUpperCase` for special cases.

Further, we generally discourage using the angular.x helpers in application code.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants