{"action":"created","issue":{"url":"https://api.github.com/repos/tc39/ecma402/issues/57","labels_url":"https://api.github.com/repos/tc39/ecma402/issues/57/labels{/name}","comments_url":"https://api.github.com/repos/tc39/ecma402/issues/57/comments","events_url":"https://api.github.com/repos/tc39/ecma402/issues/57/events","html_url":"https://github.com/tc39/ecma402/issues/57","id":118512680,"number":57,"title":"[Compatibility Hazard] ECMA 402 2nd Edition Changed the [[Call]] Behavior of Intl Constructors","user":{"login":"ericf","id":29096,"avatar_url":"https://avatars.githubusercontent.com/u/29096?v=3","gravatar_id":"","url":"https://api.github.com/users/ericf","html_url":"https://github.com/ericf","followers_url":"https://api.github.com/users/ericf/followers","following_url":"https://api.github.com/users/ericf/following{/other_user}","gists_url":"https://api.github.com/users/ericf/gists{/gist_id}","starred_url":"https://api.github.com/users/ericf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ericf/subscriptions","organizations_url":"https://api.github.com/users/ericf/orgs","repos_url":"https://api.github.com/users/ericf/repos","events_url":"https://api.github.com/users/ericf/events{/privacy}","received_events_url":"https://api.github.com/users/ericf/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/tc39/ecma402/labels/bug","name":"bug","color":"fc2929"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/tc39/ecma402/milestones/1","html_url":"https://github.com/tc39/ecma402/milestones/3rd%20Edition","labels_url":"https://api.github.com/repos/tc39/ecma402/milestones/1/labels","id":1310736,"number":1,"title":"3rd Edition","description":null,"creator":{"login":"caridy","id":38969,"avatar_url":"https://avatars.githubusercontent.com/u/38969?v=3","gravatar_id":"","url":"https://api.github.com/users/caridy","html_url":"https://github.com/caridy","followers_url":"https://api.github.com/users/caridy/followers","following_url":"https://api.github.com/users/caridy/following{/other_user}","gists_url":"https://api.github.com/users/caridy/gists{/gist_id}","starred_url":"https://api.github.com/users/caridy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caridy/subscriptions","organizations_url":"https://api.github.com/users/caridy/orgs","repos_url":"https://api.github.com/users/caridy/repos","events_url":"https://api.github.com/users/caridy/events{/privacy}","received_events_url":"https://api.github.com/users/caridy/received_events","type":"User","site_admin":false},"open_issues":5,"closed_issues":0,"state":"open","created_at":"2015-09-17T15:24:50Z","updated_at":"2015-11-24T18:40:32Z","due_on":null,"closed_at":null},"comments":17,"created_at":"2015-11-24T01:32:00Z","updated_at":"2015-11-24T22:03:47Z","closed_at":null,"body":"The 1st Edition of ECMA 402 specified the [[Call]] behavior for `Intl` constructors; e.g. [`Intl.DateTimeFormat.call(this [, locales [, options]])`](http://ecma-international.org/ecma-402/1.0/index.html#sec-12.1.2.1) to return the `this` context object that was passed-in. In the 2nd Edition, the [[Call]] behavior no longer states that the passed-in context object should be retuned. **This change is a potential compatibility hazard.**\r\n\r\nAs the developer and maintainer of the popular [FormatJS](http://formatjs.io/) i18n libraries, I've begun receiving issues from developers testing **Chrome Canary (49)** that their dates and numbers were failing for format, causing an Error to be thrown.\r\n\r\nThe high-level framework integration libs that are part of FormatJS — [react-intl](https://github.com/yahoo/react-intl), [ember-intl](https://github.com/yahoo/ember-intl), [handlebars-intl](https://github.com/yahoo/handlebars-intl) — are used by many web apps, including many of Yahoo's web apps. All these libraries use the underlying [intl-format-cache](https://github.com/yahoo/intl-format-cache) which memoizes the `Intl` constructors because they are expensive to create. The memoization technique essentially does the following:\r\n\r\n```js\r\nfunction constructIntlInstance(IntlConstructor) {\r\n    return function () {\r\n        var args = Array.prototype.slice.call(arguments);\r\n        var instance = Object.create(IntlConstructor.prototype);\r\n        IntlConstructor.apply(instance, args);\r\n        return instance;\r\n    };\r\n}\r\n```\r\n\r\n**Note:** That this code depends on the following invariant:\r\n\r\n```js\r\nvar instance = Object.create(IntlConstructor.prototype);\r\ninstance === IntlConstructor.call(instance); // true\r\n```\r\n\r\n**It is dependent on the the `Intl` constructors being `.call()`-able and the returning the context object passed-in.** This `.call()` behavior for the `Intl` constructors is supported in all ECMA 402 1st Edition implementations.\r\n\r\nAfter receiving an [issue report](https://github.com/yahoo/intl-format-cache/issues/9) about this code causing an Error to be thrown Chrome Canary (49), I dug in and found [**this recent V8 change**](https://github.com/v8/v8/commit/fa9c39eeadd8e692af03b024fe2fdcf94ad0da6b#diff-d8a48fdbaa17df29f8e916ee7f200d89L1598) which updates V8's implementation to match ECMA 402 2nd Edition, thus removing the code that returns the passed-in context object when the `Intl` constructors are `.call()`-ed.\r\n\r\nToday, I've released `intl-format-cache@2.0.5` which changes the memoization implementation to make sure the [[Construct]] behavior _always_ happens by  invoking the `Intl` constructors with `new`. Essentially doing the following:\r\n\r\n```js\r\nfunction constructIntlInstance(IntlConstructor) {\r\n    return (...args) => new IntlConstructor(...args);\r\n}\r\n```\r\n\r\nIn ES5 an equivalent would be:\r\n\r\n```js\r\nfunction constructIntlInstance(IntlConstructor) {\r\n    return function () {\r\n        var args = Array.prototype.slice.call(arguments);\r\n        return new (Function.prototype.bind.apply(IntlConstructor, [null].concat(args)))();\r\n    };\r\n}\r\n```\r\n\r\nWhile this issue is now \"fixed\" in intl-format-cache, **developers must upgrade their dependencies and re-deploy their apps.** I will help to communicate this change, but I'm worried that removing the 1st Edition [[Call]] behavior will break many apps/sites :disappointed: \r\n\r\nHow should we move forward to prevent end-users from having broken experiences?\r\n\r\n_Edited based on @rwaldron's feedback._"},"comment":{"url":"https://api.github.com/repos/tc39/ecma402/issues/comments/159418993","html_url":"https://github.com/tc39/ecma402/issues/57#issuecomment-159418993","issue_url":"https://api.github.com/repos/tc39/ecma402/issues/57","id":159418993,"user":{"login":"littledan","id":189835,"avatar_url":"https://avatars.githubusercontent.com/u/189835?v=3","gravatar_id":"","url":"https://api.github.com/users/littledan","html_url":"https://github.com/littledan","followers_url":"https://api.github.com/users/littledan/followers","following_url":"https://api.github.com/users/littledan/following{/other_user}","gists_url":"https://api.github.com/users/littledan/gists{/gist_id}","starred_url":"https://api.github.com/users/littledan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/littledan/subscriptions","organizations_url":"https://api.github.com/users/littledan/orgs","repos_url":"https://api.github.com/users/littledan/repos","events_url":"https://api.github.com/users/littledan/events{/privacy}","received_events_url":"https://api.github.com/users/littledan/received_events","type":"User","site_admin":false},"created_at":"2015-11-24T22:03:47Z","updated_at":"2015-11-24T22:03:47Z","body":"@thetalecrafter Has JSC shipped a version of Safari with the new semantics?"}}