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

Revert "Fixes: Safari's 'double finally on error bug'" #11547

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 16 additions & 17 deletions packages/ember-metal/lib/events.js
Expand Up @@ -10,7 +10,6 @@
import Ember from 'ember-metal/core';
import {
meta as metaFor,
tryFinally,
apply,
applyStr
} from 'ember-metal/utils';
Expand Down Expand Up @@ -221,10 +220,13 @@ export function suspendListener(obj, eventName, target, method, callback) {
actions[actionIndex+2] |= SUSPENDED; // mark the action as suspended
}

function tryable() { return callback.call(target); }
function finalizer() { if (actionIndex !== -1) { actions[actionIndex+2] &= ~SUSPENDED; } }

return tryFinally(tryable, finalizer);
try {
return callback.call(target);
} finally {
if (actionIndex !== -1) {
actions[actionIndex+2] &= ~SUSPENDED;
}
}
}

/**
Expand All @@ -248,12 +250,11 @@ export function suspendListeners(obj, eventNames, target, method, callback) {

var suspendedActions = [];
var actionsList = [];
var eventName, actions, i, l;

for (i=0, l=eventNames.length; i<l; i++) {
eventName = eventNames[i];
actions = actionsFor(obj, eventName);
var actionIndex = indexOf(actions, target, method);
for (let i=0, l=eventNames.length; i<l; i++) {
let eventName = eventNames[i];
let actions = actionsFor(obj, eventName);
let actionIndex = indexOf(actions, target, method);

if (actionIndex !== -1) {
actions[actionIndex+2] |= SUSPENDED;
Expand All @@ -262,16 +263,14 @@ export function suspendListeners(obj, eventNames, target, method, callback) {
}
}

function tryable() { return callback.call(target); }

function finalizer() {
for (var i = 0, l = suspendedActions.length; i < l; i++) {
var actionIndex = suspendedActions[i];
try {
return callback.call(target);
} finally {
for (let i = 0, l = suspendedActions.length; i < l; i++) {
let actionIndex = suspendedActions[i];
actionsList[i][actionIndex+2] &= ~SUSPENDED;
}
}

return tryFinally(tryable, finalizer);
}

/**
Expand Down
25 changes: 14 additions & 11 deletions packages/ember-metal/lib/instrumentation.js
@@ -1,5 +1,4 @@
import Ember from 'ember-metal/core';
import { tryCatchFinally } from 'ember-metal/utils';

/**
The purpose of the Ember Instrumentation module is
Expand Down Expand Up @@ -97,22 +96,26 @@ export function instrument(name, _payload, callback, binding) {
return callback.call(binding);
}
var payload = _payload || {};
var finalizer = _instrumentStart(name, function () {
return payload;
});
var finalizer = _instrumentStart(name, () => payload);

if (finalizer) {
var tryable = function _instrumenTryable() {
return callback.call(binding);
};
var catchable = function _instrumentCatchable(e) {
payload.exception = e;
};
return tryCatchFinally(tryable, catchable, finalizer);
return withFinalizer(callback, finalizer, payload, binding);
} else {
return callback.call(binding);
}
}

function withFinalizer(callback, finalizer, payload, binding) {
try {
return callback.call(binding);
} catch(e) {
payload.exception = e;
return payload;
} finally {
return finalizer();
}
}

// private for now
export function _instrumentStart(name, _payload) {
var listeners = cache[name];
Expand Down
1 change: 0 additions & 1 deletion packages/ember-metal/lib/main.js
Expand Up @@ -241,7 +241,6 @@ Ember.tryCatchFinally = deprecatedTryCatchFinally;
Ember.makeArray = makeArray;
Ember.canInvoke = canInvoke;
Ember.tryInvoke = tryInvoke;
Ember.tryFinally = deprecatedTryFinally;
Ember.wrap = wrap;
Ember.apply = apply;
Ember.applyStr = applyStr;
Expand Down
9 changes: 6 additions & 3 deletions packages/ember-metal/lib/property_events.js
@@ -1,6 +1,5 @@
import {
guidFor,
tryFinally
guidFor
} from 'ember-metal/utils';
import {
sendEvent,
Expand Down Expand Up @@ -276,7 +275,11 @@ function endPropertyChanges() {
*/
function changeProperties(callback, binding) {
beginPropertyChanges();
tryFinally(callback, endPropertyChanges, binding);
try {
callback.call(binding);
} finally {
endPropertyChanges.call(binding);
}
}

function notifyBeforeObservers(obj, keyName) {
Expand Down
3 changes: 1 addition & 2 deletions packages/ember-metal/lib/run_loop.js
Expand Up @@ -62,8 +62,7 @@ var backburner = new Backburner(['sync', 'actions', 'destroy'], {
@return {Object} return value from invoking the passed function.
@public
*/
export default run;
function run() {
export default function run() {
return backburner.run(...arguments);
}

Expand Down
180 changes: 1 addition & 179 deletions packages/ember-metal/lib/utils.js
Expand Up @@ -539,180 +539,6 @@ export function tryInvoke(obj, methodName, args) {
}
}

// https://github.com/emberjs/ember.js/pull/1617
var needsFinallyFix = (function() {
var count = 0;
try {
// jscs:disable
try {
} finally {
count++;
throw new Error('needsFinallyFixTest');
}
// jscs:enable
} catch (e) {}

return count !== 1;
})();

/**
Provides try/finally functionality, while working
around Safari's double finally bug.

```javascript
var tryable = function() {
someResource.lock();
runCallback(); // May throw error.
};

var finalizer = function() {
someResource.unlock();
};

Ember.tryFinally(tryable, finalizer);
```

@method tryFinally
@deprecated Use JavaScript's native try/finally
@for Ember
@param {Function} tryable The function to run the try callback
@param {Function} finalizer The function to run the finally callback
@param {Object} [binding] The optional calling object. Defaults to 'this'
@return {*} The return value is the that of the finalizer,
unless that value is undefined, in which case it is the return value
of the tryable
@private
*/

var tryFinally;
if (needsFinallyFix) {
tryFinally = function(tryable, finalizer, binding) {
var result, finalResult, finalError;

binding = binding || this;

try {
result = tryable.call(binding);
} finally {
try {
finalResult = finalizer.call(binding);
} catch (e) {
finalError = e;
}
}

if (finalError) { throw finalError; }

return (finalResult === undefined) ? result : finalResult;
};
} else {
tryFinally = function(tryable, finalizer, binding) {
var result, finalResult;

binding = binding || this;

try {
result = tryable.call(binding);
} finally {
finalResult = finalizer.call(binding);
}

return (finalResult === undefined) ? result : finalResult;
};
}

var deprecatedTryFinally = function() {
Ember.deprecate('tryFinally is deprecated. Please use JavaScript\'s native try/finally.', false);
return tryFinally.apply(this, arguments);
};

/**
Provides try/catch/finally functionality, while working
around Safari's double finally bug.

```javascript
var tryable = function() {
for (i = 0, l = listeners.length; i < l; i++) {
listener = listeners[i];
beforeValues[i] = listener.before(name, time(), payload);
}

return callback.call(binding);
};

var catchable = function(e) {
payload = payload || {};
payload.exception = e;
};

var finalizer = function() {
for (i = 0, l = listeners.length; i < l; i++) {
listener = listeners[i];
listener.after(name, time(), payload, beforeValues[i]);
}
};

Ember.tryCatchFinally(tryable, catchable, finalizer);
```

@method tryCatchFinally
@deprecated Use JavaScript's native try/catch/finally instead
@for Ember
@param {Function} tryable The function to run the try callback
@param {Function} catchable The function to run the catchable callback
@param {Function} finalizer The function to run the finally callback
@param {Object} [binding] The optional calling object. Defaults to 'this'
@return {*} The return value is the that of the finalizer,
unless that value is undefined, in which case it is the return value
of the tryable.
@private
*/
var tryCatchFinally;
if (needsFinallyFix) {
tryCatchFinally = function(tryable, catchable, finalizer, binding) {
var result, finalResult, finalError;

binding = binding || this;

try {
result = tryable.call(binding);
} catch(error) {
result = catchable.call(binding, error);
} finally {
try {
finalResult = finalizer.call(binding);
} catch (e) {
finalError = e;
}
}

if (finalError) { throw finalError; }

return (finalResult === undefined) ? result : finalResult;
};
} else {
tryCatchFinally = function(tryable, catchable, finalizer, binding) {
var result, finalResult;

binding = binding || this;

try {
result = tryable.call(binding);
} catch(error) {
result = catchable.call(binding, error);
} finally {
finalResult = finalizer.call(binding);
}

return (finalResult === undefined) ? result : finalResult;
};
}

var deprecatedTryCatchFinally = function() {
Ember.deprecate('tryCatchFinally is deprecated. Please use JavaScript\'s native try/catch/finally.', false);
return tryCatchFinally.apply(this, arguments);
};

// ........................................
// TYPING & ARRAY MESSAGING
//
Expand Down Expand Up @@ -846,9 +672,5 @@ export {
EMPTY_META,
meta,
makeArray,
tryCatchFinally,
deprecatedTryCatchFinally,
canInvoke,
tryFinally,
deprecatedTryFinally
canInvoke
};