mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-27 01:20:56 +00:00
24dc63cddd
- Bug 1205941 - Make TimerFirings logging output post-processible with fix_linux_stack.py. r=glandium. (042e3968a2) - Bug 1203427 (part 6) - Add link to MDN docs about TimerFirings logging. r=me. (19967a22e7) - missing bit of Bug 1178890 (b421ab56a1) - Bug 1207497 - Part 1: Remove use of expression closure from toolkit/, exept tests. r=Gijs (4cf4abbf3d) - Bug 1207497 - Part 2: Remove use of expression closure from tests in toolkit/. r=Gijs (6c4517c20e) - Bug 1207497 - Part 3: Fix wrong replacement in debug print in toolkit/mozapps/downloads/tests/unit/test_lowMinutes.js. r=me DONTBUILD (5311950d45) - bug 1171649 - Implement arm/iOS support in JS JITs. r=jandem (0eb06f1d3d) - Bug 1205708: Check if validation failed before reporting helper thread failure in Odin; r=luke (0bd8b70919) - missing bit of Bug 1112627: Remove redundant inline specifier in SIMD (76cea80b8c) - Bug 1189059: Replace setObjectMetadataCallback with enableObjectMetadataCallback, fix callers. r=fitzgen (053ae86af2) - Bug 1125412 - Draw a graph of memory usage, r=terrence (4ac21380a4) - Bug 1147985 - Avoid blank space when heap size graph is unavailable, r=terrence (9b48d4d435) - Bug 1170372 - Skip js1_5/Regress/regress-312588.js on SM(cgc) builds due to timeouts. (5298485837) - Bug 1160149 - Skip basic/testManyVars.js on SM(cgc) builds for frequent timeouts. (562cfc2713) - Bug 1198549 - Switch from | to $ as the preferred separator token (due to operator|), r=me\ (cc6fdb0697) - Bug 963738 - Handle Arrays in the analysis, r=terrence (589b285306) - Bug 1209696 - Check the return value of fopen, r=terrence (8c2378f3f9) - Bug 1197941 - Allow getline() to malloc its own buffer to avoid intermittent crashes, r=shu (e37b934fcc) - Bug 1180985 - Implement a JS GDB pretty-printer for JS::GCCellPtr. r=sfink (8848723b3a) - Bug 1180984 - JS GDB pretty-printers: Support Python 3. r=sfink (ae4c76014d) - Bug 1198628 - IonMonkey: ARM: Redefine FloatRegisters::Code and use it in the right way. r=nbp (d0d608b1cc) - Bug 1198145 - guard calls to getInst(). r=me (bb8c4e2e4b)
643 lines
18 KiB
JavaScript
643 lines
18 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
/**
|
|
* This file tests the Task.jsm module.
|
|
*/
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// Globals
|
|
|
|
const Cc = Components.classes;
|
|
const Ci = Components.interfaces;
|
|
const Cu = Components.utils;
|
|
const Cr = Components.results;
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
|
"resource://gre/modules/Promise.jsm");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
|
"resource://gre/modules/Services.jsm");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
|
"resource://gre/modules/Task.jsm");
|
|
|
|
/**
|
|
* Returns a promise that will be resolved with the given value, when an event
|
|
* posted on the event loop of the main thread is processed.
|
|
*/
|
|
function promiseResolvedLater(aValue) {
|
|
let deferred = Promise.defer();
|
|
Services.tm.mainThread.dispatch(() => deferred.resolve(aValue),
|
|
Ci.nsIThread.DISPATCH_NORMAL);
|
|
return deferred.promise;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// Tests
|
|
|
|
function run_test()
|
|
{
|
|
run_next_test();
|
|
}
|
|
|
|
add_test(function test_normal()
|
|
{
|
|
Task.spawn(function () {
|
|
let result = yield Promise.resolve("Value");
|
|
for (let i = 0; i < 3; i++) {
|
|
result += yield promiseResolvedLater("!");
|
|
}
|
|
throw new Task.Result("Task result: " + result);
|
|
}).then(function (result) {
|
|
do_check_eq("Task result: Value!!!", result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_exceptions()
|
|
{
|
|
Task.spawn(function () {
|
|
try {
|
|
yield Promise.reject("Rejection result by promise.");
|
|
do_throw("Exception expected because the promise was rejected.");
|
|
} catch (ex) {
|
|
// We catch this exception now, we will throw a different one later.
|
|
do_check_eq("Rejection result by promise.", ex);
|
|
}
|
|
throw new Error("Exception uncaught by task.");
|
|
}).then(function (result) {
|
|
do_throw("Unexpected success!");
|
|
}, function (ex) {
|
|
do_check_eq("Exception uncaught by task.", ex.message);
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
add_test(function test_recursion()
|
|
{
|
|
function task_fibonacci(n) {
|
|
throw new Task.Result(n < 2 ? n : (yield task_fibonacci(n - 1)) +
|
|
(yield task_fibonacci(n - 2)));
|
|
};
|
|
|
|
Task.spawn(task_fibonacci(6)).then(function (result) {
|
|
do_check_eq(8, result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_spawn_primitive()
|
|
{
|
|
function fibonacci(n) {
|
|
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
|
|
};
|
|
|
|
// Polymorphism between task and non-task functions (see "test_recursion").
|
|
Task.spawn(fibonacci(6)).then(function (result) {
|
|
do_check_eq(8, result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_spawn_function()
|
|
{
|
|
Task.spawn(function () {
|
|
return "This is not a generator.";
|
|
}).then(function (result) {
|
|
do_check_eq("This is not a generator.", result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_spawn_function_this()
|
|
{
|
|
Task.spawn(function () {
|
|
return this;
|
|
}).then(function (result) {
|
|
// Since the task function wasn't defined in strict mode, its "this" object
|
|
// should be the same as the "this" object in this function, i.e. the global
|
|
// object.
|
|
do_check_eq(result, this);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_spawn_function_this_strict()
|
|
{
|
|
"use strict";
|
|
Task.spawn(function () {
|
|
return this;
|
|
}).then(function (result) {
|
|
// Since the task function was defined in strict mode, its "this" object
|
|
// should be undefined.
|
|
do_check_eq(typeof(result), "undefined");
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_spawn_function_returning_promise()
|
|
{
|
|
Task.spawn(function () {
|
|
return promiseResolvedLater("Resolution value.");
|
|
}).then(function (result) {
|
|
do_check_eq("Resolution value.", result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_spawn_function_exceptions()
|
|
{
|
|
Task.spawn(function () {
|
|
throw new Error("Exception uncaught by task.");
|
|
}).then(function (result) {
|
|
do_throw("Unexpected success!");
|
|
}, function (ex) {
|
|
do_check_eq("Exception uncaught by task.", ex.message);
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
add_test(function test_spawn_function_taskresult()
|
|
{
|
|
Task.spawn(function () {
|
|
throw new Task.Result("Task result");
|
|
}).then(function (result) {
|
|
do_check_eq("Task result", result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_yielded_undefined()
|
|
{
|
|
Task.spawn(function () {
|
|
yield;
|
|
throw new Task.Result("We continued correctly.");
|
|
}).then(function (result) {
|
|
do_check_eq("We continued correctly.", result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_yielded_primitive()
|
|
{
|
|
Task.spawn(function () {
|
|
throw new Task.Result("Primitive " + (yield "value."));
|
|
}).then(function (result) {
|
|
do_check_eq("Primitive value.", result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_star_normal()
|
|
{
|
|
Task.spawn(function* () {
|
|
let result = yield Promise.resolve("Value");
|
|
for (let i = 0; i < 3; i++) {
|
|
result += yield promiseResolvedLater("!");
|
|
}
|
|
return "Task result: " + result;
|
|
}).then(function (result) {
|
|
do_check_eq("Task result: Value!!!", result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_star_exceptions()
|
|
{
|
|
Task.spawn(function* () {
|
|
try {
|
|
yield Promise.reject("Rejection result by promise.");
|
|
do_throw("Exception expected because the promise was rejected.");
|
|
} catch (ex) {
|
|
// We catch this exception now, we will throw a different one later.
|
|
do_check_eq("Rejection result by promise.", ex);
|
|
}
|
|
throw new Error("Exception uncaught by task.");
|
|
}).then(function (result) {
|
|
do_throw("Unexpected success!");
|
|
}, function (ex) {
|
|
do_check_eq("Exception uncaught by task.", ex.message);
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
add_test(function test_star_recursion()
|
|
{
|
|
function* task_fibonacci(n) {
|
|
return n < 2 ? n : (yield task_fibonacci(n - 1)) +
|
|
(yield task_fibonacci(n - 2));
|
|
};
|
|
|
|
Task.spawn(task_fibonacci(6)).then(function (result) {
|
|
do_check_eq(8, result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_mixed_legacy_and_star()
|
|
{
|
|
Task.spawn(function* () {
|
|
return yield (function() {
|
|
throw new Task.Result(yield 5);
|
|
})();
|
|
}).then(function (result) {
|
|
do_check_eq(5, result);
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_async_function_from_generator()
|
|
{
|
|
Task.spawn(function* () {
|
|
let object = {
|
|
asyncFunction: Task.async(function* (param) {
|
|
do_check_eq(this, object);
|
|
return param;
|
|
})
|
|
};
|
|
|
|
// Ensure the async function returns a promise that resolves as expected.
|
|
do_check_eq((yield object.asyncFunction(1)), 1);
|
|
|
|
// Ensure a second call to the async function also returns such a promise.
|
|
do_check_eq((yield object.asyncFunction(3)), 3);
|
|
}).then(function () {
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_async_function_from_function()
|
|
{
|
|
Task.spawn(function* () {
|
|
return Task.spawn(function* () {
|
|
let object = {
|
|
asyncFunction: Task.async(function (param) {
|
|
do_check_eq(this, object);
|
|
return param;
|
|
})
|
|
};
|
|
|
|
// Ensure the async function returns a promise that resolves as expected.
|
|
do_check_eq((yield object.asyncFunction(5)), 5);
|
|
|
|
// Ensure a second call to the async function also returns such a promise.
|
|
do_check_eq((yield object.asyncFunction(7)), 7);
|
|
});
|
|
}).then(function () {
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_async_function_that_throws_rejects_promise()
|
|
{
|
|
Task.spawn(function* () {
|
|
let object = {
|
|
asyncFunction: Task.async(function* () {
|
|
throw "Rejected!";
|
|
})
|
|
};
|
|
|
|
yield object.asyncFunction();
|
|
}).then(function () {
|
|
do_throw("unexpected success calling async function that throws error");
|
|
}, function (ex) {
|
|
do_check_eq(ex, "Rejected!");
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
add_test(function test_async_return_function()
|
|
{
|
|
Task.spawn(function* () {
|
|
// Ensure an async function that returns a function resolves to the function
|
|
// itself instead of calling the function and resolving to its return value.
|
|
return Task.spawn(function* () {
|
|
let returnValue = function () {
|
|
return "These aren't the droids you're looking for.";
|
|
};
|
|
|
|
let asyncFunction = Task.async(function () {
|
|
return returnValue;
|
|
});
|
|
|
|
do_check_eq((yield asyncFunction()), returnValue);
|
|
});
|
|
}).then(function () {
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_async_throw_argument_not_function()
|
|
{
|
|
Task.spawn(function* () {
|
|
// Ensure Task.async throws if its aTask argument is not a function.
|
|
Assert.throws(() => Task.async("not a function"),
|
|
/aTask argument must be a function/);
|
|
}).then(function () {
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
add_test(function test_async_throw_on_function_in_place_of_promise()
|
|
{
|
|
Task.spawn(function* () {
|
|
// Ensure Task.spawn throws if passed an async function.
|
|
Assert.throws(() => Task.spawn(Task.async(function* () {})),
|
|
/Cannot use an async function in place of a promise/);
|
|
}).then(function () {
|
|
run_next_test();
|
|
}, function (ex) {
|
|
do_throw("Unexpected error: " + ex);
|
|
});
|
|
});
|
|
|
|
|
|
////////////////// Test rewriting of stack traces
|
|
|
|
// Backup Task.Debuggin.maintainStack.
|
|
// Will be restored by `exit_stack_tests`.
|
|
let maintainStack;
|
|
add_test(function enter_stack_tests() {
|
|
maintainStack = Task.Debugging.maintainStack;
|
|
Task.Debugging.maintainStack = true;
|
|
run_next_test();
|
|
});
|
|
|
|
|
|
/**
|
|
* Ensure that a list of frames appear in a stack, in the right order
|
|
*/
|
|
function do_check_rewritten_stack(frames, ex) {
|
|
do_print("Checking that the expected frames appear in the right order");
|
|
do_print(frames.join(", "));
|
|
let stack = ex.stack;
|
|
do_print(stack);
|
|
|
|
let framesFound = 0;
|
|
let lineNumber = 0;
|
|
let reLine = /([^\r\n])+/g;
|
|
let match;
|
|
while (framesFound < frames.length && (match = reLine.exec(stack))) {
|
|
let line = match[0];
|
|
let frame = frames[framesFound];
|
|
do_print("Searching for " + frame + " in line " + line);
|
|
if (line.indexOf(frame) != -1) {
|
|
do_print("Found " + frame);
|
|
++framesFound;
|
|
} else {
|
|
do_print("Didn't find " + frame);
|
|
}
|
|
}
|
|
|
|
if (framesFound >= frames.length) {
|
|
return;
|
|
}
|
|
do_throw("Did not find: " + frames.slice(framesFound).join(", ") +
|
|
" in " + stack.substr(reLine.lastIndex));
|
|
|
|
do_print("Ensuring that we have removed Task.jsm, Promise.jsm");
|
|
do_check_true(stack.indexOf("Task.jsm") == -1);
|
|
do_check_true(stack.indexOf("Promise.jsm") == -1);
|
|
do_check_true(stack.indexOf("Promise-backend.js") == -1);
|
|
}
|
|
|
|
|
|
// Test that we get an acceptable rewritten stack when we launch
|
|
// an error in a Task.spawn.
|
|
add_test(function test_spawn_throw_stack() {
|
|
Task.spawn(function* task_spawn_throw_stack() {
|
|
for (let i = 0; i < 5; ++i) {
|
|
yield Promise.resolve(); // Without stack rewrite, this would lose valuable information
|
|
}
|
|
throw new Error("BOOM");
|
|
}).then(do_throw, function(ex) {
|
|
do_check_rewritten_stack(["task_spawn_throw_stack",
|
|
"test_spawn_throw_stack"],
|
|
ex);
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
// Test that we get an acceptable rewritten stack when we yield
|
|
// a rejection in a Task.spawn.
|
|
add_test(function test_spawn_yield_reject_stack() {
|
|
Task.spawn(function* task_spawn_yield_reject_stack() {
|
|
for (let i = 0; i < 5; ++i) {
|
|
yield Promise.resolve(); // Without stack rewrite, this would lose valuable information
|
|
}
|
|
yield Promise.reject(new Error("BOOM"));
|
|
}).then(do_throw, function(ex) {
|
|
do_check_rewritten_stack(["task_spawn_yield_reject_stack",
|
|
"test_spawn_yield_reject_stack"],
|
|
ex);
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
// Test that we get an acceptable rewritten stack when we launch
|
|
// an error in a Task.async function.
|
|
add_test(function test_async_function_throw_stack() {
|
|
let task_async_function_throw_stack = Task.async(function*() {
|
|
for (let i = 0; i < 5; ++i) {
|
|
yield Promise.resolve(); // Without stack rewrite, this would lose valuable information
|
|
}
|
|
throw new Error("BOOM");
|
|
})().then(do_throw, function(ex) {
|
|
do_check_rewritten_stack(["task_async_function_throw_stack",
|
|
"test_async_function_throw_stack"],
|
|
ex);
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
// Test that we get an acceptable rewritten stack when we launch
|
|
// an error in a Task.async function.
|
|
add_test(function test_async_function_yield_reject_stack() {
|
|
let task_async_function_yield_reject_stack = Task.async(function*() {
|
|
for (let i = 0; i < 5; ++i) {
|
|
yield Promise.resolve(); // Without stack rewrite, this would lose valuable information
|
|
}
|
|
yield Promise.reject(new Error("BOOM"));
|
|
})().then(do_throw, function(ex) {
|
|
do_check_rewritten_stack(["task_async_function_yield_reject_stack",
|
|
"test_async_function_yield_reject_stack"],
|
|
ex);
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
// Test that we get an acceptable rewritten stack when we launch
|
|
// an error in a Task.async function.
|
|
add_test(function test_async_method_throw_stack() {
|
|
let object = {
|
|
task_async_method_throw_stack: Task.async(function*() {
|
|
for (let i = 0; i < 5; ++i) {
|
|
yield Promise.resolve(); // Without stack rewrite, this would lose valuable information
|
|
}
|
|
throw new Error("BOOM");
|
|
})
|
|
};
|
|
object.task_async_method_throw_stack().then(do_throw, function(ex) {
|
|
do_check_rewritten_stack(["task_async_method_throw_stack",
|
|
"test_async_method_throw_stack"],
|
|
ex);
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
// Test that we get an acceptable rewritten stack when we launch
|
|
// an error in a Task.async function.
|
|
add_test(function test_async_method_yield_reject_stack() {
|
|
let object = {
|
|
task_async_method_yield_reject_stack: Task.async(function*() {
|
|
for (let i = 0; i < 5; ++i) {
|
|
yield Promise.resolve(); // Without stack rewrite, this would lose valuable information
|
|
}
|
|
yield Promise.reject(new Error("BOOM"));
|
|
})
|
|
};
|
|
object.task_async_method_yield_reject_stack().then(do_throw, function(ex) {
|
|
do_check_rewritten_stack(["task_async_method_yield_reject_stack",
|
|
"test_async_method_yield_reject_stack"],
|
|
ex);
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
// Test that two tasks whose execution takes place interleaved do not capture each other's stack.
|
|
add_test(function test_throw_stack_do_not_capture_the_wrong_task() {
|
|
for (let iter_a of [3, 4, 5]) { // Vary the interleaving
|
|
for (let iter_b of [3, 4, 5]) {
|
|
Task.spawn(function* task_a() {
|
|
for (let i = 0; i < iter_a; ++i) {
|
|
yield Promise.resolve();
|
|
}
|
|
throw new Error("BOOM");
|
|
}).then(do_throw, function(ex) {
|
|
do_check_rewritten_stack(["task_a",
|
|
"test_throw_stack_do_not_capture_the_wrong_task"],
|
|
ex);
|
|
do_check_true(!ex.stack.includes("task_b"));
|
|
run_next_test();
|
|
});
|
|
Task.spawn(function* task_b() {
|
|
for (let i = 0; i < iter_b; ++i) {
|
|
yield Promise.resolve();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// Put things together
|
|
add_test(function test_throw_complex_stack()
|
|
{
|
|
// Setup the following stack:
|
|
// inner_method()
|
|
// task_3()
|
|
// task_2()
|
|
// task_1()
|
|
// function_3()
|
|
// function_2()
|
|
// function_1()
|
|
// test_throw_complex_stack()
|
|
(function function_1() {
|
|
return (function function_2() {
|
|
return (function function_3() {
|
|
return Task.spawn(function* task_1() {
|
|
yield Promise.resolve();
|
|
try {
|
|
yield Task.spawn(function* task_2() {
|
|
yield Promise.resolve();
|
|
yield Task.spawn(function* task_3() {
|
|
yield Promise.resolve();
|
|
let inner_object = {
|
|
inner_method: Task.async(function*() {
|
|
throw new Error("BOOM");
|
|
})
|
|
};
|
|
yield Promise.resolve();
|
|
yield inner_object.inner_method();
|
|
});
|
|
});
|
|
} catch (ex) {
|
|
yield Promise.resolve();
|
|
throw ex;
|
|
}
|
|
});
|
|
})();
|
|
})();
|
|
})().then(
|
|
() => do_throw("Shouldn't have succeeded"),
|
|
(ex) => {
|
|
let expect = ["inner_method",
|
|
"task_3",
|
|
"task_2",
|
|
"task_1",
|
|
"function_3",
|
|
"function_2",
|
|
"function_1",
|
|
"test_throw_complex_stack"];
|
|
do_check_rewritten_stack(expect, ex);
|
|
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
add_test(function test_without_maintainStack() {
|
|
do_print("Calling generateReadableStack without a Task");
|
|
Task.Debugging.generateReadableStack(new Error("Not a real error"));
|
|
|
|
Task.Debugging.maintainStack = false;
|
|
|
|
do_print("Calling generateReadableStack with neither a Task nor maintainStack");
|
|
Task.Debugging.generateReadableStack(new Error("Not a real error"));
|
|
|
|
do_print("Calling generateReadableStack without maintainStack");
|
|
Task.spawn(function*() {
|
|
Task.Debugging.generateReadableStack(new Error("Not a real error"));
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
add_test(function exit_stack_tests() {
|
|
Task.Debugging.maintainStack = maintainStack;
|
|
run_next_test();
|
|
});
|
|
|