mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
Backed out changeset 0f5ac8b278f8 (bug 1929055
) for causing mochitest failures @ test_xrayToExplicitResourceManagement CLOSED TREE
This commit is contained in:
parent
d120154203
commit
c473fbfb32
@ -222,5 +222,3 @@ skip-if = ["bits == 32"] # Large ArrayBuffers not supported on 32-bit.
|
||||
["test_xrayToJS.xhtml"]
|
||||
|
||||
["test_xrayic.xhtml"]
|
||||
|
||||
["test_xrayToExplicitResourceManagement.html"]
|
||||
|
@ -1,342 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1929055
|
||||
-->
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Test for Bug 1929055</title>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://global/skin" />
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
<script>
|
||||
var { AppConstants } = SpecialPowers.ChromeUtils.importESModule(
|
||||
"resource://gre/modules/AppConstants.sys.mjs"
|
||||
);
|
||||
const isExplicitResourceManagementEnabled = AppConstants.ENABLE_EXPLICIT_RESOURCE_MANAGEMENT;
|
||||
|
||||
async function go() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["javascript.options.experimental.explicit_resource_management", true]],
|
||||
});
|
||||
|
||||
if (!isExplicitResourceManagementEnabled) {
|
||||
await SpecialPowers.popPrefEnv();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
let simpleConstructors = [
|
||||
'DisposableStack',
|
||||
'AsyncDisposableStack',
|
||||
];
|
||||
|
||||
const errorObjectClasses = [
|
||||
'SuppressedError',
|
||||
]
|
||||
|
||||
simpleConstructors = simpleConstructors.concat(errorObjectClasses);
|
||||
|
||||
let global = Cu.getGlobalForObject.bind(Cu);
|
||||
|
||||
const iwin = document.getElementById('ifr').contentWindow;
|
||||
|
||||
// Copied from js/xpconnect/tests/chrome/test_xrayToJS.xhtml
|
||||
// ==== BEGIN ===
|
||||
|
||||
// Test constructors that can be instantiated with zero arguments, or with
|
||||
// a fixed set of arguments provided using `...rest`.
|
||||
for (let c of simpleConstructors) {
|
||||
var args = [];
|
||||
if (typeof c === 'object') {
|
||||
args = c.args;
|
||||
c = c.name;
|
||||
}
|
||||
ok(iwin[c], "Constructors appear: " + c);
|
||||
is(iwin[c], Cu.unwaiveXrays(iwin.wrappedJSObject[c]),
|
||||
"we end up with the appropriate constructor: " + c);
|
||||
is(Cu.unwaiveXrays(Cu.waiveXrays(new iwin[c](...args)).constructor), iwin[c],
|
||||
"constructor property is set up right: " + c);
|
||||
let expectedProto = Cu.isOpaqueWrapper(new iwin[c](...args)) ?
|
||||
iwin.Object.prototype : iwin[c].prototype;
|
||||
is(Object.getPrototypeOf(new iwin[c](...args)), expectedProto,
|
||||
"prototype is correct: " + c);
|
||||
is(global(new iwin[c](...args)), iwin, "Got the right global: " + c);
|
||||
}
|
||||
|
||||
var gPrototypeProperties = {};
|
||||
var gConstructorProperties = {};
|
||||
// Properties which cannot be invoked if callable without potentially
|
||||
// rendering the object useless.
|
||||
var gStatefulProperties = {};
|
||||
|
||||
function testProtoCallables(protoCallables, xray, xrayProto, localProto, callablesExcluded) {
|
||||
// Handle undefined callablesExcluded.
|
||||
let dontCall = callablesExcluded ?? [];
|
||||
for (let name of protoCallables) {
|
||||
info("Running tests for property: " + name);
|
||||
// Test both methods and getter properties.
|
||||
function lookupCallable(obj) {
|
||||
let desc = null;
|
||||
do {
|
||||
desc = Object.getOwnPropertyDescriptor(obj, name);
|
||||
if (desc) {
|
||||
break;
|
||||
}
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
} while (obj);
|
||||
return desc ? (desc.get || desc.value) : undefined;
|
||||
};
|
||||
ok(xrayProto.hasOwnProperty(name), `proto should have the property '${name}' as own`);
|
||||
ok(!xray.hasOwnProperty(name), `instance should not have the property '${name}' as own`);
|
||||
let method = lookupCallable(xrayProto);
|
||||
is(typeof method, 'function', "Methods from Xrays are functions");
|
||||
is(global(method), window, "Methods from Xrays are local");
|
||||
ok(method instanceof Function, "instanceof works on methods from Xrays");
|
||||
is(lookupCallable(xrayProto), method, "Holder caching works properly");
|
||||
is(lookupCallable(xray), method, "Proto props resolve on the instance");
|
||||
let local = lookupCallable(localProto);
|
||||
is(method.length, local.length, "Function.length identical");
|
||||
if (!method.length && !dontCall.includes(name)) {
|
||||
is(method.call(xray) + "", local.call(xray) + "",
|
||||
"Xray and local method results stringify identically");
|
||||
|
||||
// If invoking this method returns something non-Xrayable (opaque), the
|
||||
// stringification is going to return [object Object].
|
||||
// This happens for set[@@iterator] and other Iterator objects.
|
||||
let callable = lookupCallable(xray.wrappedJSObject);
|
||||
if (!Cu.isOpaqueWrapper(method.call(xray)) && callable) {
|
||||
is(method.call(xray) + "",
|
||||
callable.call(xray.wrappedJSObject) + "",
|
||||
"Xray and waived method results stringify identically");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testCtorCallables(ctorCallables, xrayCtor, localCtor) {
|
||||
for (let name of ctorCallables) {
|
||||
// Don't try to test Function.prototype, since that is in fact a callable
|
||||
// but doesn't really do the things we expect callables to do here
|
||||
// (e.g. it's in the wrong global, since it gets Xrayed itself).
|
||||
if (name == "prototype" && localCtor.name == "Function") {
|
||||
continue;
|
||||
}
|
||||
info(`Running tests for property: ${localCtor.name}.${name}`);
|
||||
// Test both methods and getter properties.
|
||||
function lookupCallable(obj) {
|
||||
let desc = null;
|
||||
do {
|
||||
desc = Object.getOwnPropertyDescriptor(obj, name);
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
} while (!desc);
|
||||
return desc.get || desc.value;
|
||||
};
|
||||
|
||||
ok(xrayCtor.hasOwnProperty(name), "ctor should have the property as own");
|
||||
let method = lookupCallable(xrayCtor);
|
||||
is(typeof method, 'function', "Methods from ctor Xrays are functions");
|
||||
is(global(method), window, "Methods from ctor Xrays are local");
|
||||
ok(method instanceof Function,
|
||||
"instanceof works on methods from ctor Xrays");
|
||||
is(lookupCallable(xrayCtor), method,
|
||||
"Holder caching works properly on ctors");
|
||||
let local = lookupCallable(localCtor);
|
||||
is(method.length, local.length,
|
||||
"Function.length identical for method from ctor");
|
||||
// Don't try to do the return-value check on Date.now(), since there is
|
||||
// absolutely no reason it should return the same value each time.
|
||||
//
|
||||
// Also don't try to do the return-value check on Regexp.lastMatch and
|
||||
// Regexp["$&"] (which are aliases), because they get state off the global
|
||||
// they live in, as far as I can tell, so testing them over Xrays will be
|
||||
// wrong: on the Xray they will actaully get the lastMatch of _our_
|
||||
// global, not the Xrayed one.
|
||||
if (!method.length &&
|
||||
!(localCtor.name == "Date" && name == "now") &&
|
||||
!(localCtor.name == "RegExp" && (name == "lastMatch" || name == "$&"))) {
|
||||
is(method.call(xrayCtor) + "", local.call(xrayCtor) + "",
|
||||
"Xray and local method results stringify identically on constructors");
|
||||
is(method.call(xrayCtor) + "",
|
||||
lookupCallable(xrayCtor.wrappedJSObject).call(xrayCtor.wrappedJSObject) + "",
|
||||
"Xray and waived method results stringify identically");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function filterOut(array, props) {
|
||||
return array.filter(p => !props.includes(p));
|
||||
}
|
||||
|
||||
function propertyIsGetter(obj, name) {
|
||||
return !!Object.getOwnPropertyDescriptor(obj, name).get;
|
||||
}
|
||||
|
||||
function constructorProps(arr) {
|
||||
// Some props live on all constructors
|
||||
return arr.concat(["prototype", "length", "name"]);
|
||||
}
|
||||
|
||||
// Sort an array that may contain symbols as well as strings.
|
||||
function sortProperties(arr) {
|
||||
function sortKey(prop) {
|
||||
return typeof prop + ":" + prop.toString();
|
||||
}
|
||||
arr.sort((a, b) => sortKey(a) < sortKey(b) ? -1 : +1);
|
||||
}
|
||||
|
||||
function testXray(classname, xray, xray2, propsToSkip, ctorPropsToSkip = []) {
|
||||
propsToSkip = propsToSkip || [];
|
||||
let xrayProto = Object.getPrototypeOf(xray);
|
||||
let localProto = window[classname].prototype;
|
||||
let desiredProtoProps = Object.getOwnPropertyNames(localProto).sort();
|
||||
|
||||
is(desiredProtoProps.toSource(),
|
||||
gPrototypeProperties[classname].filter(id => typeof id === "string").toSource(),
|
||||
"A property on the " + classname +
|
||||
" prototype has changed! You need a security audit from an XPConnect peer");
|
||||
is(Object.getOwnPropertySymbols(localProto).map(uneval).sort().toSource(),
|
||||
gPrototypeProperties[classname].filter(id => typeof id !== "string").map(uneval).sort().toSource(),
|
||||
"A symbol-keyed property on the " + classname +
|
||||
" prototype has been changed! You need a security audit from an XPConnect peer");
|
||||
|
||||
let protoProps = filterOut(desiredProtoProps, propsToSkip);
|
||||
let protoCallables = protoProps.filter(name => propertyIsGetter(localProto, name, classname) ||
|
||||
typeof localProto[name] == 'function' &&
|
||||
name != 'constructor');
|
||||
let callablesExcluded = gStatefulProperties[classname];
|
||||
ok(!!protoCallables.length, "Need something to test");
|
||||
is(xrayProto, iwin[classname].prototype, "Xray proto is correct");
|
||||
is(xrayProto, xray.__proto__, "Proto accessors agree");
|
||||
var protoProto = classname == "Object" ? null : iwin.Object.prototype;
|
||||
is(Object.getPrototypeOf(xrayProto), protoProto, "proto proto is correct");
|
||||
testProtoCallables(protoCallables, xray, xrayProto, localProto, callablesExcluded);
|
||||
is(Object.getOwnPropertyNames(xrayProto).sort().toSource(),
|
||||
protoProps.toSource(), "getOwnPropertyNames works");
|
||||
is(Object.getOwnPropertySymbols(xrayProto).map(uneval).sort().toSource(),
|
||||
gPrototypeProperties[classname].filter(id => typeof id !== "string" && !propsToSkip.includes(id))
|
||||
.map(uneval).sort().toSource(),
|
||||
"getOwnPropertySymbols works");
|
||||
|
||||
is(xrayProto.constructor, iwin[classname], "constructor property works");
|
||||
|
||||
xrayProto.expando = 42;
|
||||
is(xray.expando, 42, "Xrayed instances see proto expandos");
|
||||
is(xray2.expando, 42, "Xrayed instances see proto expandos");
|
||||
|
||||
// Now test constructors
|
||||
let localCtor = window[classname];
|
||||
let xrayCtor = xrayProto.constructor;
|
||||
// We already checked that this is the same as iwin[classname]
|
||||
|
||||
let desiredCtorProps =
|
||||
Object.getOwnPropertyNames(localCtor).sort();
|
||||
is(desiredCtorProps.toSource(),
|
||||
gConstructorProperties[classname].filter(id => typeof id === "string").toSource(),
|
||||
"A property on the " + classname +
|
||||
" constructor has changed! You need a security audit from an XPConnect peer");
|
||||
let desiredCtorSymbols =
|
||||
Object.getOwnPropertySymbols(localCtor).map(uneval).sort()
|
||||
is(desiredCtorSymbols.toSource(),
|
||||
gConstructorProperties[classname].filter(id => typeof id !== "string").map(uneval).sort().toSource(),
|
||||
"A symbol-keyed property on the " + classname +
|
||||
" constructor has been changed! You need a security audit from an XPConnect peer");
|
||||
|
||||
let ctorProps = filterOut(desiredCtorProps, ctorPropsToSkip);
|
||||
let ctorSymbols = filterOut(desiredCtorSymbols, ctorPropsToSkip.map(uneval));
|
||||
let ctorCallables = ctorProps.filter(name => propertyIsGetter(localCtor, name, classname) ||
|
||||
typeof localCtor[name] == 'function');
|
||||
testCtorCallables(ctorCallables, xrayCtor, localCtor);
|
||||
is(Object.getOwnPropertyNames(xrayCtor).sort().toSource(),
|
||||
ctorProps.toSource(), "getOwnPropertyNames works on Xrayed ctors");
|
||||
is(Object.getOwnPropertySymbols(xrayCtor).map(uneval).sort().toSource(),
|
||||
ctorSymbols.toSource(), "getOwnPropertySymbols works on Xrayed ctors");
|
||||
}
|
||||
|
||||
// ==== END ===
|
||||
|
||||
gPrototypeProperties.DisposableStack = [
|
||||
"adopt", "constructor", "defer", "dispose", "disposed", "move", "use",
|
||||
Symbol.toStringTag, Symbol.dispose
|
||||
];
|
||||
gStatefulProperties.DisposableStack = ["dispose", Symbol.dispose, "move"];
|
||||
gConstructorProperties.DisposableStack = constructorProps([]);
|
||||
|
||||
gPrototypeProperties.AsyncDisposableStack = [
|
||||
"adopt", "constructor", "defer", "disposeAsync", "disposed", "move", "use",
|
||||
Symbol.toStringTag, Symbol.asyncDispose
|
||||
];
|
||||
gStatefulProperties.AsyncDisposableStack = ["disposeAsync", Symbol.asyncDispose, "move"];
|
||||
gConstructorProperties.AsyncDisposableStack = constructorProps([]);
|
||||
|
||||
// Sort all the lists so we don't need to mutate them later (or copy them
|
||||
// again to sort them).
|
||||
for (let c of Object.keys(gPrototypeProperties))
|
||||
sortProperties(gPrototypeProperties[c]);
|
||||
for (let c of Object.keys(gConstructorProperties))
|
||||
sortProperties(gConstructorProperties[c]);
|
||||
|
||||
function testDisposableStack() {
|
||||
testXray("DisposableStack", new iwin.DisposableStack(), new iwin.DisposableStack());
|
||||
}
|
||||
|
||||
function testAsyncDisposableStack() {
|
||||
testXray("AsyncDisposableStack", new iwin.AsyncDisposableStack(), new iwin.AsyncDisposableStack());
|
||||
}
|
||||
|
||||
function testSuppressedError() {
|
||||
const c = errorObjectClasses[0];
|
||||
const args = ['error', 'suppressed', 'some message'];
|
||||
var e = new iwin.SuppressedError(...args);
|
||||
|
||||
// Copied from js/xpconnect/tests/chrome/test_xrayToJS.xhtml
|
||||
// ==== BEGIN ===
|
||||
|
||||
is(Object.getPrototypeOf(e).name, c, "Prototype has correct name");
|
||||
is(Object.getPrototypeOf(Object.getPrototypeOf(e)), iwin.Error.prototype, "Dependent prototype set up correctly");
|
||||
is(e.name, c, "Exception name inherited correctly");
|
||||
|
||||
function testProperty(name, criterion, goodReplacement, faultyReplacement) {
|
||||
ok(criterion(e[name]), name + " property is correct: " + e[name]);
|
||||
e.wrappedJSObject[name] = goodReplacement;
|
||||
is(e[name], goodReplacement, name + " property ok after replacement: " + goodReplacement);
|
||||
e.wrappedJSObject[name] = faultyReplacement;
|
||||
is(e[name], name == 'message' ? "" : undefined, name + " property skipped after suspicious replacement");
|
||||
}
|
||||
testProperty('message', x => x == 'some message', 'some other message', 42);
|
||||
testProperty('fileName', x => x == '', 'otherFilename.html', new iwin.Object());
|
||||
testProperty('columnNumber', x => x == 1, 99, 99.5);
|
||||
testProperty('lineNumber', x => x == 0, 50, 'foo');
|
||||
|
||||
// ==== END ===
|
||||
|
||||
e.wrappedJSObject.error = 42;
|
||||
is(e.wrappedJSObject.error, 42, "errors is a plain data property");
|
||||
is(e.error, 42, "error visible over Xrays");
|
||||
|
||||
e.wrappedJSObject.suppressed = 43;
|
||||
is(e.wrappedJSObject.suppressed, 43, "suppressed is a plain data property");
|
||||
is(e.suppressed, 43, "suppressed visible over Xrays");
|
||||
}
|
||||
|
||||
testDisposableStack();
|
||||
|
||||
testAsyncDisposableStack();
|
||||
|
||||
testSuppressedError();
|
||||
|
||||
await SpecialPowers.popPrefEnv();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1929055">Mozilla Bug 1929055</a>
|
||||
|
||||
<iframe id="ifr" onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" />
|
||||
</body>
|
||||
|
||||
</html>
|
@ -19,13 +19,6 @@ export var AppConstants = Object.freeze({
|
||||
false,
|
||||
#endif
|
||||
|
||||
ENABLE_EXPLICIT_RESOURCE_MANAGEMENT:
|
||||
#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
|
||||
RELEASE_OR_BETA:
|
||||
#ifdef RELEASE_OR_BETA
|
||||
true,
|
||||
|
Loading…
Reference in New Issue
Block a user