Ember.js: v3.6.0-beta.3 JQuery.extend (recursively) is broken

Created on 8 Nov 2018  路  13Comments  路  Source: emberjs/ember.js

We use some jquery plugins (e.g.: bootstrap-daterangepicker), which uses the extend method from jquery. In v3.6.0-beta.3, this fails as jquery recursively iterates through the [] property of an array (we use the array prototype extensions of Ember)

[email protected]
$.extend(true, {}, {a:['a']}) gives

{a: Array(1)}

[email protected]
$.extend(true, {}, {a:['a']}) gives

jquery.js:282 Uncaught RangeError: Maximum call stack size exceeded
    at Function.jQuery.extend.jQuery.fn.extend (jquery.js:282)
    at Function.jQuery.extend.jQuery.fn.extend (jquery.js:282)
    at Function.jQuery.extend.jQuery.fn.extend (jquery.js:282)
    at Function.jQuery.extend.jQuery.fn.extend (jquery.js:282)
    at Function.jQuery.extend.jQuery.fn.extend (jquery.js:282)
    at Function.jQuery.extend.jQuery.fn.extend (jquery.js:282)
    at Function.jQuery.extend.jQuery.fn.extend (jquery.js:282)
    at Function.jQuery.extend.jQuery.fn.extend (jquery.js:282)
    at Function.jQuery.extend.jQuery.fn.extend (jquery.js:282)
    at Function.jQuery.extend.jQuery.fn.extend (jquery.js:282)
Bug Regression

Most helpful comment

Now someone just needs to fix it :D

All 13 comments

This is using the same version of jQuery between the two?

I鈥檓 not immediately aware of a change that would have caused this. We will probably need to bisect to track it down...

To reproduce, I created a new project (so no extra dependencies)

ember new extend --yarn

This installs [email protected]
I run the default application and in the browser console I executed the command

$.extend(true, {}, {a:['a']})

Then I upgraded ember

yarn upgrade [email protected]

And this gives the error

JQuery uses for ( name in options ) construct to iterate over the properties.

In ember 3.5.1

Object.getOwnPropertyDescriptor([].__proto__, '[]')

returns

{get: 茠, set: undefined, enumerable: false, configurable: true}

and in ember 3.6.0-beta.3
the result is

{get: 茠, set: undefined, enumerable: true, configurable: true}

As a for...in construct iterates over all enumerable properties, in ember 3.5.1 the [] is not included, but it is included in ember 3.6.0-beta.3

I'm seeing a very similar issue with ember-inputmask:

[Error] RangeError: Maximum call stack size exceeded.
    get (vendor.js:28394)
    extend (vendor.js:99178)
    extend (vendor.js:99190)
    extend (vendor.js:99190)
    extend (vendor.js:99190)
    extend (vendor.js:99190)
    ....
    extend (vendor.js:99190)

Stacktrace shows it's this line of code code which triggers it - which is also a .extend() like the jQuery problem above: https://github.com/RobinHerbots/Inputmask/blob/5.x/lib/dependencyLibs/inputmask.dependencyLib.js#L317

I've tried all beta versions (1-4) and the problem exists in all versions.

As a workaround I execute the following code in an initializer

        // TODO: remove once https://github.com/emberjs/ember.js/issues/17190 has been fixed
        const properties = ['[]', 'firstObject', 'lastObject', 'hasArrayObservers', '@each'];
        properties.forEach(property => {
            const desc = Object.getOwnPropertyDescriptor([].__proto__, property);
            desc.enumerable = false;
            Object.defineProperty([].__proto__, property, desc);
        });

This _seems_ like a regression of the fixes in https://github.com/emberjs/ember.js/pull/16169 which was _specifically_ trying to address this issue...

I can confirm that this problem still happens in 3.6 and 3.7.0-beta.1.
One easy way to check for regression is to run for (var x in []) console.log(x):

  • In vanilla JS: logs nothing
  • In Ember 3.5.1 logs _super
  • In Ember 3.6.0 & 3.7.0-beta.1 it logs _super, [], firstObject, lastObject hasArrayObservers, and @each

See also https://github.com/ember-cli/ember-cli/issues/8295

Update: I created a PR to incorporate a test for this, though it doesn't actually fix the problem.

This is using the same version of jQuery between the two?

I鈥檓 not immediately aware of a change that would have caused this. We will probably need to bisect to track it down...

Running git bisect with the test I wrote in #17374 suggests that the problem was introduced by 02af02546a05cd372bf53033318f65af7b544023 246435e7260f45d9e5cc35a4a8b4de4f011f3625

Hmm, that seems somewhat surprising because I think that landed after this issue was reported right?

OK, I am trying again but using more automation (was running the test myself before and may have made a mistake).

Create executable test.sh script with the following contents:

rm -rf dist/ node_modules/
yarn
ember build
node -e "require('./dist/ember.debug.js'); const a = []; for (let p in a) { if (a[p] === a) { throw new Error(\`a[\"\${p}\"] === a\`)}}"

Then bisect like this

git checkout master
git bisect start
git bad
git bisect good v3.5.1
git bisect run ./test.sh

When I ran this just now it finished with:

246435e7260f45d9e5cc35a4a8b4de4f011f3625 is the first bad commit
commit 246435e7260f45d9e5cc35a4a8b4de4f011f3625
Author: bekzod <[email protected]>
Date:   Mon Jun 11 21:42:16 2018 +0500

    avoid double define for native descriptors

:040000 040000 173ea3396625a0bf0d5ddb72c7591daa93151e33 a4a4903a3f9c3ef40ba3ac9699056005d1b2046c M  packages
bisect run success

Awesome, that makes sense!

Now someone just needs to fix it :D

Fixed by #17374

Was this page helpful?
0 / 5 - 0 ratings