Skip to content

Commit

Permalink
fix ScriptException when bound functions are called inside Promise.th…
Browse files Browse the repository at this point in the history
…en()
  • Loading branch information
rbri committed Feb 19, 2023
1 parent a21c0bc commit efb944c
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/org/mozilla/javascript/BoundFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,13 @@ public BoundFunction(

@Override
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] extraArgs) {
Scriptable callThis = boundThis != null ? boundThis : ScriptRuntime.getTopCallScope(cx);
Scriptable callThis = boundThis;
if (callThis == null && ScriptRuntime.hasTopCall(cx)) {
callThis = ScriptRuntime.getTopCallScope(cx);
}
if (callThis == null) {
callThis = getTopLevelScope(scope);
}
return targetFunction.call(cx, scope, callThis, concat(boundArgs, extraArgs));
}

Expand Down
100 changes: 100 additions & 0 deletions testsrc/jstests/es6/promises_bind.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
load('testsrc/assert.js');

(function() {
// Test before clearing global (fails otherwise)
assertEquals("[object Promise]",
Object.prototype.toString.call(new Promise(function() {})));
})();

function defer(constructor) {
var resolve, reject;
var promise = new constructor((res, rej) => { resolve = res; reject = rej });
return {
promise: promise,
resolve: resolve,
reject: reject
};
}

var asyncAssertsExpected = 0;

function assertAsyncRan() { ++asyncAssertsExpected }

function assertAsync(b, s) {
if (b) {
//print(s, "succeeded")
} else {
AbortJS(s + " FAILED!") // Simply throwing here will have no effect.
}
--asyncAssertsExpected
}

function assertLater(f, name) {
assertFalse(f()); // should not be true synchronously
++asyncAssertsExpected;
var iterations = 0;
function runAssertion() {
if (f()) {
//print(name, "succeeded");
--asyncAssertsExpected;
} else if (iterations++ < 10) {
EnqueueMicrotask(runAssertion);
} else {
AbortJS(name + " FAILED!");
}
}
EnqueueMicrotask(runAssertion);
}

function assertAsyncDone(iteration) {
var iteration = iteration || 0;
EnqueueMicrotask(function() {
if (asyncAssertsExpected === 0)
assertAsync(true, "all")
else if (iteration > 10) // Shouldn't take more.
assertAsync(false, "all... " + asyncAssertsExpected)
else
assertAsyncDone(iteration + 1)
});
}

(function() {
var res = '';
var f = function () { res += this; }

Promise.resolve().then(f.bind(null));

assertLater(function() { return res == "[object Object]"; }, "Promise.resolve().then(f.bind(null))");
})();

(function() {
var res = '';
var f = function () { res += this; }

Promise.resolve().then(f.bind('abcd'));

assertLater(function() { return res == "abcd"; }, "Promise.resolve().then(f.bind('abcd'))");
})();

(function() {
var res = '';
var f = function () { res += this; }

Promise.resolve().then(() => f.bind(null).call());

assertLater(function() { return res == "[object Object]"; }, "Promise.resolve().then(() => f.bind(null).call())");
})();

(function() {
var res = '';
var f = function () { res += this; }

Promise.resolve().then(() => f.bind('abcd').call());

assertLater(function() { return res == "abcd"; }, "Promise.resolve().then(() => f.bind('abcd').call())");
})();


assertAsyncDone()

'success';
14 changes: 14 additions & 0 deletions testsrc/org/mozilla/javascript/tests/es6/PromiseBindTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.javascript.tests.es6;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.drivers.LanguageVersion;
import org.mozilla.javascript.drivers.RhinoTest;
import org.mozilla.javascript.drivers.ScriptTestsBase;

@RhinoTest("testsrc/jstests/es6/promises_bind.js")
@LanguageVersion(Context.VERSION_ES6)
public class PromiseBindTest extends ScriptTestsBase {}

0 comments on commit efb944c

Please sign in to comment.