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] Fix stack overflow in wrap. #12132

Merged
merged 1 commit into from
Aug 18, 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
7 changes: 5 additions & 2 deletions packages/ember-metal/lib/mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ import {
} from 'ember-metal/events';
import { isStream } from 'ember-metal/streams/utils';

function ROOT() {}
ROOT.__hasSuper = false;

var REQUIRED;
var a_slice = [].slice;

Expand Down Expand Up @@ -185,7 +188,7 @@ function applyMergedProperties(obj, key, value, values) {
}

if (hasFunction) {
newBase._super = function () {};
newBase._super = ROOT;
}

return newBase;
Expand Down Expand Up @@ -372,7 +375,7 @@ function applyMixin(obj, mixins, partial) {
var keys = [];
var key, value, desc;

obj._super = function () {};
obj._super = ROOT;

// Go through all mixins and hashes passed in, and:
//
Expand Down
70 changes: 44 additions & 26 deletions packages/ember-metal/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,31 @@ export function guidFor(obj) {
}


var sourceAvailable = (function() {
return this;
}).toString().indexOf('return this;') > -1;
const checkHasSuper = (function () {
let sourceAvailable = (function() {
return this;
}).toString().indexOf('return this;') > -1;

if (sourceAvailable) {
return function checkHasSuper(func) {
return func.toString().indexOf('_super') > -1;
};
}

return function checkHasSuper() {
return true;
};
}());

function ROOT() {}
ROOT.__hasSuper = false;

function hasSuper(func) {
if (func.__hasSuper === undefined) {
func.__hasSuper = checkHasSuper(func);
}
return func.__hasSuper;
}

/**
Wraps the passed function so that `this._super` will point to the superFunc
Expand All @@ -270,43 +292,39 @@ var sourceAvailable = (function() {
@param {Function} superFunc The super function.
@return {Function} wrapped function.
*/
export function wrap(func, _superFunc) {
var superFunc = _superFunc;
var hasSuper;
if (sourceAvailable) {
hasSuper = func.__hasSuper;

if (hasSuper === undefined) {
hasSuper = func.toString().indexOf('_super') > -1;
func.__hasSuper = hasSuper;
}

if (!hasSuper) {
return func;
}
export function wrap(func, superFunc) {
if (!hasSuper(func)) {
return func;
}

if (superFunc.wrappedFunction === undefined) {
// terminate _super to prevent infinite recursion
superFunc = wrap(superFunc, function () {});
// ensure an unwrapped super that calls _super is wrapped with a terminal _super
if (!superFunc.wrappedFunction && hasSuper(superFunc)) {
return _wrap(func, _wrap(superFunc, ROOT));
}

return _wrap(func, superFunc);
}

function _wrap(func, superFunc) {
function superWrapper() {
var ret;
var orig = this._super;
let orig = this._super;
let length = arguments.length;
let ret;
this._super = superFunc;
switch (arguments.length) {
switch (length) {
case 0: ret = func.call(this); break;
case 1: ret = func.call(this, arguments[0]); break;
case 2: ret = func.call(this, arguments[0], arguments[1]); break;
case 3: ret = func.call(this, arguments[0], arguments[1], arguments[2]); break;
case 4: ret = func.call(this, arguments[0], arguments[1], arguments[2], arguments[3]); break;
case 5: ret = func.call(this, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); break;
default: ret = func.apply(this, arguments); break;
default:
// v8 bug potentially incorrectly deopts this function: https://code.google.com/p/v8/issues/detail?id=3709
// we may want to keep this around till this ages out on mobile
let args = new Array(length);
for (var x = 0; x < length; x++) {
args[x] = arguments[x];
}
ret = func.apply(this, args);
break;
}
this._super = orig;
return ret;
Expand Down