Bug 552560 - Remove support for __parent__. r=mrbkap

This commit is contained in:
Jeff Walden 2010-04-11 13:51:00 -07:00
parent 4532818401
commit 23aeebc511
34 changed files with 219 additions and 434 deletions

View File

@ -3101,10 +3101,10 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
//
// Compiling it using (for example) the first document's global
// object would cause JS to keep a reference via the __proto__ or
// __parent__ pointer to the first document's global. If that
// happened, our script object would reference the first document,
// and the first document would indirectly reference the prototype
// document because it keeps the prototype cache alive. Circularity!
// parent pointer to the first document's global. If that happened,
// our script object would reference the first document, and the
// first document would indirectly reference the prototype document
// because it keeps the prototype cache alive. Circularity!
nsresult rv;
// Use the prototype document's special context

View File

@ -1266,3 +1266,55 @@ nsDOMWindowUtils::GetVisitedDependentComputedStyle(
return rv;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetParent()
{
// This wasn't privileged in the past, but better to expose less than more.
if (!IsUniversalXPConnectCapable()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsIXPConnect> xpc = nsContentUtils::XPConnect();
// get the xpconnect native call context
nsAXPCNativeCallContext *cc = nsnull;
xpc->GetCurrentNativeCallContext(&cc);
if(!cc)
return NS_ERROR_FAILURE;
// Get JSContext of current call
JSContext* cx;
nsresult rv = cc->GetJSContext(&cx);
if(NS_FAILED(rv) || !cx)
return NS_ERROR_FAILURE;
// get place for return value
jsval *rval = nsnull;
rv = cc->GetRetValPtr(&rval);
if(NS_FAILED(rv) || !rval)
return NS_ERROR_FAILURE;
// get argc and argv and verify arg count
PRUint32 argc;
rv = cc->GetArgc(&argc);
if(NS_FAILED(rv))
return NS_ERROR_FAILURE;
if(argc != 1)
return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
jsval* argv;
rv = cc->GetArgvPtr(&argv);
if(NS_FAILED(rv) || !argv)
return NS_ERROR_FAILURE;
// first argument must be an object
if(JSVAL_IS_PRIMITIVE(argv[0]))
return NS_ERROR_XPC_BAD_CONVERT_JS;
*rval = OBJECT_TO_JSVAL(JS_GetParent(cx, JSVAL_TO_OBJECT(argv[0])));
cc->SetReturnValueWasSet(PR_TRUE);
return NS_OK;
}

View File

@ -53,7 +53,7 @@ interface nsIDOMEvent;
interface nsITransferable;
interface nsIQueryContentEventResult;
[scriptable, uuid(22a62b54-bcf5-422a-a329-fed4de5e78b2)]
[scriptable, uuid(352ff0af-bb38-496a-a067-b54771168d6d)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -655,4 +655,12 @@ interface nsIDOMWindowUtils : nsISupports {
AString getVisitedDependentComputedStyle(in nsIDOMElement aElement,
in AString aPseudoElement,
in AString aPropertyName);
/**
* Returns the parent of obj.
*
* @param obj The JavaScript object whose parent is to be gotten.
* @return the parent.
*/
void getParent(/* obj */);
};

View File

@ -77,21 +77,6 @@ function inspect(obj) {
return;
}
print("* Object type: "+typeof obj+"\n");
if (typeof obj != "xml") {
print("* Parent chain: ");
try {
var parent = obj.__parent__;
while(parent) {
try {
print(parent);
}
catch(e) { dump("(?)"); }
finally { dump(" "); }
parent = parent.__parent__;
}
} catch(e) { dump("...(?)"); }
print("\n");
}
switch(typeof obj) {
case "object":
print("* Prototype chain: ");

View File

@ -1345,7 +1345,6 @@ static JSStdName standard_class_names[] = {
static JSStdName object_prototype_names[] = {
/* Object.prototype properties (global delegates to Object.prototype). */
{js_InitObjectClass, EAGER_ATOM(proto), NULL},
{js_InitObjectClass, EAGER_ATOM(parent), NULL},
#if JS_HAS_TOSOURCE
{js_InitObjectClass, EAGER_ATOM(toSource), NULL},
#endif

View File

@ -147,7 +147,6 @@ const char *const js_common_atom_names[] = {
js_name_str, /* nameAtom */
js_next_str, /* nextAtom */
js_noSuchMethod_str, /* noSuchMethodAtom */
js_parent_str, /* parentAtom */
js_proto_str, /* protoAtom */
js_set_str, /* setAtom */
js_stack_str, /* stackAtom */
@ -220,7 +219,6 @@ const char js_name_str[] = "name";
const char js_next_str[] = "next";
const char js_noSuchMethod_str[] = "__noSuchMethod__";
const char js_object_str[] = "object";
const char js_parent_str[] = "__parent__";
const char js_proto_str[] = "__proto__";
const char js_setter_str[] = "setter";
const char js_set_str[] = "set";

View File

@ -259,7 +259,6 @@ struct JSAtomState {
JSAtom *nameAtom;
JSAtom *nextAtom;
JSAtom *noSuchMethodAtom;
JSAtom *parentAtom;
JSAtom *protoAtom;
JSAtom *setAtom;
JSAtom *stackAtom;
@ -388,7 +387,6 @@ extern const char js_namespace_str[];
extern const char js_next_str[];
extern const char js_noSuchMethod_str[];
extern const char js_object_str[];
extern const char js_parent_str[];
extern const char js_proto_str[];
extern const char js_ptagc_str[];
extern const char js_qualifier_str[];

View File

@ -832,10 +832,9 @@ struct JSRuntime {
void *gcExtraRootsData;
/*
* Used to serialize cycle checks when setting __proto__ or __parent__ by
* requesting the GC handle the required cycle detection. If the GC hasn't
* been poked, it won't scan for garbage. This member is protected by
* rt->gcLock.
* Used to serialize cycle checks when setting __proto__ by requesting the
* GC handle the required cycle detection. If the GC hasn't been poked, it
* won't scan for garbage. This member is protected by rt->gcLock.
*/
JSSetSlotRequest *setSlotRequests;

View File

@ -2688,10 +2688,9 @@ static JSBool
EmitSpecialPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
{
/*
* Special case for obj.__proto__ and obj.__parent__ to deoptimize away
* from fast paths in the interpreter and trace recorder, which skip dense
* array instances by going up to Array.prototype before looking up the
* property name.
* Special case for obj.__proto__ to deoptimize away from fast paths in the
* interpreter and trace recorder, which skip dense array instances by
* going up to Array.prototype before looking up the property name.
*/
JSAtomListElement *ale = cg->atomList.add(cg->parser, pn->pn_atom);
if (!ale)
@ -2713,10 +2712,9 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg,
JS_ASSERT(pn->pn_arity == PN_NAME);
pn2 = pn->maybeExpr();
/* Special case deoptimization on __proto__ and __parent__. */
/* Special case deoptimization for __proto__. */
if ((op == JSOP_GETPROP || op == JSOP_CALLPROP) &&
(pn->pn_atom == cx->runtime->atomState.protoAtom ||
pn->pn_atom == cx->runtime->atomState.parentAtom)) {
pn->pn_atom == cx->runtime->atomState.protoAtom) {
if (pn2 && !js_EmitTree(cx, cg, pn2))
return JS_FALSE;
return EmitSpecialPropOp(cx, pn, callContext ? JSOP_CALLELEM : JSOP_GETELEM, cg);
@ -2802,13 +2800,8 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg,
return JS_FALSE;
}
/*
* Special case deoptimization on __proto__ and __parent__, as
* above.
*/
if (pndot->pn_arity == PN_NAME &&
(pndot->pn_atom == cx->runtime->atomState.protoAtom ||
pndot->pn_atom == cx->runtime->atomState.parentAtom)) {
/* Special case deoptimization on __proto__, as above. */
if (pndot->pn_arity == PN_NAME && pndot->pn_atom == cx->runtime->atomState.protoAtom) {
if (!EmitSpecialPropOp(cx, pndot, JSOP_GETELEM, cg))
return JS_FALSE;
} else if (!EmitAtomOp(cx, pndot, PN_OP(pndot), cg)) {
@ -7409,9 +7402,8 @@ js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array)
*
* In such cases, naively following ECMA leads to wrongful sharing of RegExp
* objects, which makes for collisions on the lastIndex property (especially
* for global regexps) and on any ad-hoc properties. Also, __proto__ and
* __parent__ refer to the pre-compilation prototype and global objects, a
* pigeon-hole problem for instanceof tests.
* for global regexps) and on any ad-hoc properties. Also, __proto__ refers to
* the pre-compilation prototype, a pigeon-hole problem for instanceof tests.
*/
uintN
JSCGObjectList::index(JSObjectBox *objbox)

View File

@ -126,59 +126,29 @@ JSClass js_ObjectClass = {
#if JS_HAS_OBJ_PROTO_PROP
static JSBool
obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
obj_getProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
static JSBool
obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
obj_setProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
static JSPropertySpec object_props[] = {
/* These two must come first; see object_props[slot].name usage below. */
{js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED,
obj_getSlot, obj_setSlot},
{js_parent_str,JSSLOT_PARENT,JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED,
obj_getSlot, obj_setSlot},
{js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED, obj_getProto, obj_setProto},
{0,0,0,0,0}
};
/* NB: JSSLOT_PROTO and JSSLOT_PARENT are already indexes into object_props. */
#define JSSLOT_COUNT 2
static JSBool
ReportStrictSlot(JSContext *cx, uint32 slot)
obj_getProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
if (slot == JSSLOT_PROTO)
return JS_TRUE;
return JS_ReportErrorFlagsAndNumber(cx,
JSREPORT_WARNING | JSREPORT_STRICT,
js_GetErrorMessage, NULL,
JSMSG_DEPRECATED_USAGE,
object_props[slot].name);
}
static JSBool
obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
jsid propid;
JSAccessMode mode;
uintN attrs;
JSObject *pobj;
JSClass *clasp;
if (id == INT_TO_JSVAL(JSSLOT_PROTO)) {
propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
mode = JSACC_PROTO;
} else {
propid = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);
mode = JSACC_PARENT;
}
JS_ASSERT(id == INT_TO_JSID(JSSLOT_PROTO));
/* Let obj->checkAccess get the slot's value, based on the access mode. */
if (!obj->checkAccess(cx, propid, mode, vp, &attrs))
uintN attrs;
id = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
if (!obj->checkAccess(cx, id, JSACC_PROTO, vp, &attrs))
return JS_FALSE;
pobj = JSVAL_TO_OBJECT(*vp);
if (pobj) {
clasp = pobj->getClass();
if (JSObject *pobj = JSVAL_TO_OBJECT(*vp)) {
JSClass *clasp = pobj->getClass();
if (clasp == &js_CallClass || clasp == &js_BlockClass) {
/* Censor activations and lexical scopes per ECMA-262. */
*vp = JSVAL_NULL;
@ -188,8 +158,8 @@ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
* censor. So it cannot escape to scripts.
*/
JS_ASSERT(clasp != &js_DeclEnvClass);
if (pobj->map->ops->thisObject) {
pobj = pobj->map->ops->thisObject(cx, pobj);
if (JSObjectOp thisObject = pobj->map->ops->thisObject) {
pobj = thisObject(cx, pobj);
if (!pobj)
return JS_FALSE;
*vp = OBJECT_TO_JSVAL(pobj);
@ -200,17 +170,14 @@ obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
}
static JSBool
obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
obj_setProto(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
JSObject *pobj;
uint32 slot;
jsid propid;
uintN attrs;
JS_ASSERT(id == INT_TO_JSID(JSSLOT_PROTO));
if (!JSVAL_IS_OBJECT(*vp))
return JS_TRUE;
pobj = JSVAL_TO_OBJECT(*vp);
JSObject *pobj = JSVAL_TO_OBJECT(*vp);
if (pobj) {
/*
* Innerize pobj here to avoid sticking unwanted properties on the
@ -221,16 +188,13 @@ obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
if (!pobj)
return JS_FALSE;
}
slot = (uint32) JSVAL_TO_INT(id);
if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, slot))
uintN attrs;
id = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
if (!obj->checkAccess(cx, id, JSAccessMode(JSACC_PROTO|JSACC_WRITE), vp, &attrs))
return JS_FALSE;
/* __parent__ is readonly and permanent, only __proto__ may be set. */
propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
if (!obj->checkAccess(cx, propid, (JSAccessMode)(JSACC_PROTO|JSACC_WRITE), vp, &attrs))
return JS_FALSE;
return js_SetProtoOrParent(cx, obj, slot, pobj, JS_TRUE);
return js_SetProtoOrParent(cx, obj, JSSLOT_PROTO, pobj, JS_TRUE);
}
#else /* !JS_HAS_OBJ_PROTO_PROP */
@ -300,15 +264,8 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
}
if (ssr.cycle) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CYCLIC_VALUE,
#if JS_HAS_OBJ_PROTO_PROP
object_props[slot].name
#else
(slot == JSSLOT_PROTO) ? js_proto_str
: js_parent_str
#endif
);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CYCLIC_VALUE,
(slot == JSSLOT_PROTO) ? js_proto_str : "parent");
return JS_FALSE;
}
}
@ -3839,8 +3796,8 @@ js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
AutoValueRooter tvr(cx, cval);
/*
* If proto or parent are NULL, set them to Constructor.prototype and/or
* Constructor.__parent__, just like JSOP_NEW does.
* If proto is NULL, set it to Constructor.prototype, just like JSOP_NEW
* does, likewise for the new object's parent.
*/
ctor = JSVAL_TO_OBJECT(cval);
if (!parent)
@ -5691,10 +5648,10 @@ js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
* We don't want to require all classes to supply a checkAccess hook; we
* need that hook only for certain classes used when precompiling scripts
* and functions ("brutal sharing"). But for general safety of built-in
* magic properties such as __proto__ and __parent__, we route all access
* checks, even for classes that stub out checkAccess, through the global
* checkObjectAccess hook. This covers precompilation-based sharing and
* (possibly unintended) runtime sharing across trust boundaries.
* magic properties like __proto__, we route all access checks, even for
* classes that stub out checkAccess, through the global checkObjectAccess
* hook. This covers precompilation-based sharing and (possibly
* unintended) runtime sharing across trust boundaries.
*/
clasp = pobj->getClass();
check = clasp->checkAccess;

View File

@ -364,7 +364,7 @@ struct JSObject {
JSObject *parent = getParent();
if (parent)
JS_CALL_OBJECT_TRACER(trc, parent, "__parent__");
JS_CALL_OBJECT_TRACER(trc, parent, "parent");
}
JSObject *getGlobal();

View File

@ -3333,9 +3333,8 @@ BEGIN_CASE(JSOP_INITMETHOD)
* So check first.
*
* On a hit, if the cached sprop has a non-default setter, it must be
* __proto__ or __parent__. If sprop->parent != scope->lastProperty(),
* there is a repeated property name. The fast path does not handle these
* two cases.
* __proto__. If sprop->parent != scope->lastProperty(), there is a
* repeated property name. The fast path does not handle these two cases.
*/
if (CX_OWNS_OBJECT_TITLE(cx, obj) &&
JS_PROPERTY_CACHE(cx).testForInit(rt, regs.pc, obj, scope, &sprop, &entry) &&

View File

@ -3658,6 +3658,24 @@ Elapsed(JSContext *cx, uintN argc, jsval *vp)
return JS_FALSE;
}
static JSBool
Parent(JSContext *cx, uintN argc, jsval *vp)
{
if (argc != 1) {
JS_ReportError(cx, "Wrong number of arguments");
return JS_FALSE;
}
jsval v = JS_ARGV(cx, vp)[0];
if (JSVAL_IS_PRIMITIVE(v)) {
JS_ReportError(cx, "Only objects have parents!");
return JS_FALSE;
}
*vp = OBJECT_TO_JSVAL(JS_GetParent(cx, JSVAL_TO_OBJECT(v)));
return JS_TRUE;
}
#ifdef XP_UNIX
#include <fcntl.h>
@ -3911,6 +3929,7 @@ static JSFunctionSpec shell_functions[] = {
JS_FN("parse", Parse, 1,0),
JS_FN("timeout", Timeout, 1,0),
JS_FN("elapsed", Elapsed, 0,0),
JS_FN("parent", Parent, 1,0),
JS_FS_END
};
@ -4018,7 +4037,8 @@ static const char *const shell_help_messages[] = {
"timeout([seconds])\n"
" Get/Set the limit in seconds for the execution time for the current context.\n"
" A negative value (default) means that the execution time is unlimited.",
"elapsed() Execution time elapsed for the current context.\n",
"elapsed() Execution time elapsed for the current context.",
"parent(obj) Returns the parent of obj.\n",
};
/* Help messages must match shell functions. */

View File

@ -37,7 +37,7 @@
gTestfile = 'regress-313080.js';
var summary = "Regression - Do not crash calling __proto__, __parent__";
var summary = "Regression - Do not crash calling __proto__";
var BUGNUMBER = 313080;
var actual = 'No Crash';
var expect = 'No Crash';
@ -48,7 +48,6 @@ START(summary);
try
{
<element/>.__proto__();
<element/>.__parent__();
<element/>.function::__proto__();
}
catch(e)

View File

@ -38,7 +38,7 @@
var gTestfile = 'regress-164697.js';
//-----------------------------------------------------------------------------
var BUGNUMBER = 164697;
var summary = '(instance.__parent__ == constructor.__parent__)';
var summary = '(parent(instance) == parent(constructor))';
var actual = '';
var expect = '';
@ -61,13 +61,10 @@ runtest('new Function(";")', 'Function');
runtest('[]', 'Array');
runtest('new Array()', 'Array');
runtest('""', 'String');
runtest('new String()', 'String');
runtest('true', 'Boolean');
runtest('new Boolean()', 'Boolean');
runtest('1', 'Number');
runtest('new Number("1")', 'Number');
runtest('new Date()', 'Date');
@ -84,8 +81,9 @@ function runtest(myinstance, myconstructor)
try
{
expr = '(' + myinstance + ').__parent__ == ' +
myconstructor + '.__parent__';
expr =
'parent(' + myinstance + ') == ' +
'parent(' + myconstructor + ')';
printStatus(expr);
actual = eval(expr).toString();
}

View File

@ -1,147 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is JavaScript Engine testing utilities.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corp.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* igor@fastmail.fm, pschwartau@netscape.com
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
*
* Date: 29 Sep 2003
* SUMMARY: Testing __parent__ and __proto__ of Script object
*
* See http://bugzilla.mozilla.org/show_bug.cgi?id=220584
*/
//-----------------------------------------------------------------------------
var gTestfile = 'regress-220584.js';
var UBound = 0;
var BUGNUMBER = 220584;
var summary = 'Testing __parent__ and __proto__ of Script object';
var status = '';
var statusitems = [];
var actual = '';
var actualvalues = [];
var expect= '';
var expectedvalues = [];
var s;
// invoke |Script| as a function
status = inSection(1);
if (typeof Script == 'undefined')
{
reportCompare("Script not defined, Test skipped.",
"Script not defined, Test skipped.",
summary);
}
else
{
s = Script('1;');
actual = s instanceof Object;
expect = true;
addThis();
status = inSection(2);
actual = (s.__parent__ == undefined) || (s.__parent__ == null);
expect = false;
addThis();
status = inSection(3);
actual = (s.__proto__ == undefined) || (s.__proto__ == null);
expect = false;
addThis();
status = inSection(4);
actual = (s + '').length > 0;
expect = true;
addThis();
}
// invoke |Script| as a constructor
status = inSection(5);
if (typeof Script == 'undefined')
{
print('Test skipped. Script not defined.');
}
else
{
s = new Script('1;');
actual = s instanceof Object;
expect = true;
addThis();
status = inSection(6);
actual = (s.__parent__ == undefined) || (s.__parent__ == null);
expect = false;
addThis();
status = inSection(7);
actual = (s.__proto__ == undefined) || (s.__proto__ == null);
expect = false;
addThis();
status = inSection(8);
actual = (s + '').length > 0;
expect = true;
addThis();
}
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function addThis()
{
statusitems[UBound] = status;
actualvalues[UBound] = actual;
expectedvalues[UBound] = expect;
UBound++;
}
function test()
{
enterFunc('test');
printBugNumber(BUGNUMBER);
printStatus(summary);
for (var i=0; i<UBound; i++)
{
reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]);
}
exitFunc ('test');
}

View File

@ -38,7 +38,7 @@
var gTestfile = 'regress-312278.js';
//-----------------------------------------------------------------------------
var BUGNUMBER = 312278;
var summary = 'Do no access GC-ed object in Error.prototype.toSource';
var summary = 'Do not access GC-ed object in Error.prototype.toSource';
var actual = 'No Crash';
var expect = 'No Crash';
@ -51,7 +51,7 @@ function wrapInsideWith(obj)
with (obj) {
f = function() { }
}
return f.__parent__;
return parent(f);
}
function customToSource()

View File

@ -54,7 +54,7 @@ function test()
jit(true);
eval("(function() { for (var j = 0; j < 4; ++j) { /x/.__parent__; } })")();
eval("(function() { for (var j = 0; j < 4; ++j) { parent(/x/); } })")();
jit(false);

View File

@ -58,7 +58,7 @@ function test()
{
filler += "\u5050";
}
var blkobj = function() { let x; yield function(){}.__parent__; }().next();
var blkobj = function() { let x; yield parent(function(){}); }().next();
gc();
for(var i = 0; i < 1024; i++)
{

View File

@ -58,7 +58,7 @@ function test()
try
{
(function() {
let b = function(){}.__parent__;
let b = parent(function(){});
print(b[1] = throwError);
})();
}

View File

@ -27,7 +27,7 @@ function makeWorkerFn(id) {
for (n in bar) {
for (m in bar[n]) {}
}
for (n in {}.__parent__) {}
for (n in parent({})) {}
};
}
@ -42,8 +42,8 @@ var actual;
expect = actual = 'No crash';
if (typeof scatter == 'undefined') {
print('Test skipped. scatter not defined.');
} else if (!("__parent__" in {})) {
print('Test skipped. __parent__ not defined.');
} else if (typeof parent === "undefined") {
print('Test skipped, no parent() function.');
} else {
for (let i = 0; i < LOOP_COUNT; i++) {
foo = 0;

View File

@ -1,26 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
function mk() {
return (function () {});
}
function f() {
var j = 55;
var f = function () {
return j;
};
var g = function() {};
var a = [ mk(), f, g, mk(), mk() ];
for (var i = 0; i < 5; ++i) {
a[i].p = 99;
}
}
f();
for (var i = 0; i < 9; i++)
({__parent__: []} = []);

View File

@ -1,2 +0,0 @@
for (var i = 0; i < 9; i++)
({__parent__: []} = []);

View File

@ -759,6 +759,24 @@ Options(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
return JS_TRUE;
}
static JSBool
Parent(JSContext *cx, uintN argc, jsval *vp)
{
if (argc != 1) {
JS_ReportError(cx, "Wrong number of arguments");
return JS_FALSE;
}
jsval v = JS_ARGV(cx, vp)[0];
if (JSVAL_IS_PRIMITIVE(v)) {
JS_ReportError(cx, "Only objects have parents!");
return JS_FALSE;
}
*vp = OBJECT_TO_JSVAL(JS_GetParent(cx, JSVAL_TO_OBJECT(v)));
return JS_TRUE;
}
static JSFunctionSpec glob_functions[] = {
{"print", Print, 0,0,0},
{"readline", ReadLine, 1,0,0},
@ -774,6 +792,7 @@ static JSFunctionSpec glob_functions[] = {
#endif
{"clear", Clear, 1,0,0},
{"options", Options, 0,0,0},
JS_FN("parent", Parent, 1,0),
#ifdef DEBUG
{"dumpHeap", DumpHeap, 5,0,0},
#endif

View File

@ -594,9 +594,8 @@ XPC_COW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
}
if (interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_PROTO) ||
interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_PARENT) ||
interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS)) {
// No getting or setting __proto__ or __parent__ on my object.
// No getting or setting __proto__ on my object.
return ThrowException(NS_ERROR_INVALID_ARG, cx); // XXX better error message
}

View File

@ -1382,7 +1382,7 @@ XPCNativeWrapper::CreateExplicitWrapper(JSContext *cx,
// parents for it.
JS_LockGCThing(cx, wrapperObj);
// A deep XPCNativeWrapper has a __parent__ chain that mirrors its
// A deep XPCNativeWrapper has a parent chain that mirrors its
// XPCWrappedNative's chain.
if (!MirrorWrappedNativeParent(cx, wrappedNative, &parent))
return JS_FALSE;

View File

@ -62,7 +62,6 @@ const char* XPCJSRuntime::mStrings[] = {
"item", // IDX_ITEM
"__proto__", // IDX_PROTO
"__iterator__", // IDX_ITERATOR
"__parent__", // IDX_PARENT
"__exposedProps__" // IDX_EXPOSEDPROPS
};

View File

@ -669,7 +669,6 @@ public:
IDX_ITEM ,
IDX_PROTO ,
IDX_ITERATOR ,
IDX_PARENT ,
IDX_EXPOSEDPROPS ,
IDX_TOTAL_COUNT // just a count of the above
};
@ -3013,7 +3012,7 @@ public:
* @param s the native object we're working with
* @param type the type of object that s is
* @param iid the interface of s that we want
* @param scope the default scope to put on the new JSObject's __parent__
* @param scope the default scope to put on the new JSObject's parent
* chain
* @param pErr [out] relevant error code, if any.
*/
@ -3044,8 +3043,7 @@ public:
* @param Interface the interface of src that we want
* @param cache the wrapper cache for src (may be null, in which case src
* will be QI'ed to get the cache)
* @param scope the default scope to put on the new JSObject's __parent__
* chain
* @param scope the default scope to put on the new JSObject's parent chain
* @param allowNativeWrapper if true, this method may wrap the resulting
* JSObject in an XPCNativeWrapper and return that, as needed.
* @param isGlobal
@ -3100,8 +3098,7 @@ public:
* @param type the type of objects in the array
* @param iid the interface of each object in the array that we want
* @param count the number of items in the array
* @param scope the default scope to put on the new JSObjects' __parent__
* chain
* @param scope the default scope to put on the new JSObjects' parent chain
* @param pErr [out] relevant error code, if any.
*/
static JSBool NativeArray2JS(XPCLazyCallContext& ccx,
@ -4275,8 +4272,7 @@ public:
*
* @param ccx the context for the whole procedure
* @param variant the variant to convert
* @param scope the default scope to put on the new JSObject's __parent__
* chain
* @param scope the default scope to put on the new JSObject's parent chain
* @param pErr [out] relevant error code, if any.
* @param pJSVal [out] the resulting jsval.
*/

View File

@ -1,74 +0,0 @@
const LOOP_COUNT = 10000;
const THREAD_COUNT = 10;
const nsIThread = Components.interfaces.nsIThread;
const ThreadContractID = "@mozilla.org/thread;1";
const Thread = new Components.Constructor(ThreadContractID, "nsIThread", "init");
var foo;
var bar;
function threadProc() {
foo = this.id+1;
bar[this.id] = {p : 0};
var n, m;
for(n in bar) {
// Uncommenting the line below makes this a lot more likely to deadlock.
for(m in bar[n]) {}
}
// Commented this because I was thinking that the printf impl being called
// on so many thread might be contributing to some apparent memory
// corruption cases.
// print(" printed from other thread "+this.id+". foo is: "+foo);
for(n in this.__parent__) /* print(n) */;
}
function runThreads() {
print(" printed from main thread. foo is "+foo);
var threads = new Array(THREAD_COUNT);
var i;
for(i = 0; i < THREAD_COUNT; i++) {
var runable = {run : threadProc, id : i};
threads[i] = new Thread(runable, 0,
nsIThread.PRIORITY_NORMAL,
nsIThread.SCOPE_GLOBAL,
nsIThread.STATE_JOINABLE);
}
print(" printed from main thread. foo is "+foo);
// var main_thread = threads[0].currentThread;
for(i = THREAD_COUNT-1; i >= 0; i--) {
// main_thread.sleep(1);
threads[i].join();
}
print(" printed from main thread. foo is "+foo);
}
var total_interval = 0;
for(i = 0; i < LOOP_COUNT; i++) {
var start_time = new Date().getTime()/1000;
foo = 0;
bar = new Array(THREAD_COUNT);
print("--- loop number "+i);
runThreads();
var end_time = new Date().getTime()/1000;
var interval = parseInt(100*(end_time - start_time),10)/100;
print(" Interval = "+interval+ " seconds.");
// ignore first loop
if(i) {
total_interval += end_time - start_time;
var average_interval = parseInt(100*(total_interval / i),10)/100
print("Average Interval = "+average_interval+" seconds.");
}
}

View File

@ -7,10 +7,16 @@
.getInterface(Components.interfaces.nsIDOMWindowUtils);
ok(utils.getClassName(wrapper) === expected, note);
}
function check_parent(ok, obj, expected, note) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
ok(utils.getParent(obj) === expected, note);
}
function run_test(ok, xpcnw, sjow) {
// both wrappers should point to our window: XOW
check_wrapper(ok, ok, "Function", "functions are wrapped properly")
ok(ok.__parent__ == window, "ok is parented correctly");
check_parent(ok, ok, window, "ok is parented correctly");
check_wrapper(ok, xpcnw, "XPCCrossOriginWrapper", "XPCNWs are transformed correctly");
check_wrapper(ok, sjow, "XPCCrossOriginWrapper", "SJOWs are transformed correctly");

View File

@ -62,8 +62,7 @@ function COWTests() {
var empty = {};
isProp(getCOW(empty), "foo", undefined, "empty.foo is undefined");
const PROPS_TO_TEST = ['foo', '__parent__', '__proto__',
'prototype', 'constructor'];
const PROPS_TO_TEST = ['foo', '__proto__', 'prototype', 'constructor'];
var strict = { __exposedProps__: {} };
var strictCOW = getCOW(strict);

View File

@ -20,11 +20,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=366645
/** Test for Bug 366645 **/
function getParent(obj) {
return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.getParent(obj);
}
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var Cc = Components.classes;
var Ci = Components.interfaces;
var table = Cc["@mozilla.org/url-classifier/table;1?type=url"].createInstance();
var componentScope = table.wrappedJSObject.__parent__;
var componentScope = getParent(table.wrappedJSObject);
ok(!!componentScope, "unable to get wrapped js object");
var PROT_EnchashDecrypter = componentScope.PROT_EnchashDecrypter;

View File

@ -233,16 +233,16 @@ function run_abstract_class_tests()
do_check_class(ctypes.CType, "Function");
do_check_class(ctypes.CType.prototype, "CType");
do_check_true(ctypes.CType.__parent__ === ctypes);
do_check_true(ctypes.CType.__proto__ === ctypes.__parent__.Function.prototype);
do_check_true(ctypes.CType instanceof ctypes.__parent__.Function);
do_check_true(parent(ctypes.CType) === ctypes);
do_check_true(ctypes.CType.__proto__ === parent(ctypes).Function.prototype);
do_check_true(ctypes.CType instanceof parent(ctypes).Function);
do_check_true(ctypes.CType.hasOwnProperty("prototype"));
do_check_throws(function() { ctypes.CType.prototype(); }, Error);
do_check_throws(function() { new ctypes.CType.prototype() }, Error);
do_check_true(ctypes.CType.prototype.__parent__ === ctypes);
do_check_true(ctypes.CType.prototype.__proto__ === ctypes.__parent__.Function.prototype);
do_check_true(ctypes.CType.prototype instanceof ctypes.__parent__.Function);
do_check_true(parent(ctypes.CType.prototype) === ctypes);
do_check_true(ctypes.CType.prototype.__proto__ === parent(ctypes).Function.prototype);
do_check_true(ctypes.CType.prototype instanceof parent(ctypes).Function);
do_check_true(ctypes.CType.prototype.hasOwnProperty("constructor"));
do_check_true(ctypes.CType.prototype.constructor === ctypes.CType);
@ -270,13 +270,13 @@ function run_abstract_class_tests()
do_check_class(ctypes.CData, "Function");
do_check_class(ctypes.CData.prototype, "CData");
do_check_true(ctypes.CData.__parent__ === ctypes);
do_check_true(parent(ctypes.CData) === ctypes);
do_check_true(ctypes.CData.__proto__ === ctypes.CType.prototype);
do_check_true(ctypes.CData instanceof ctypes.CType);
do_check_true(ctypes.CData.hasOwnProperty("prototype"));
do_check_true(ctypes.CData.prototype.__parent__ === ctypes);
do_check_true(ctypes.CData.prototype.__proto__ === ctypes.__parent__.Object.prototype);
do_check_true(parent(ctypes.CData.prototype) === ctypes);
do_check_true(ctypes.CData.prototype.__proto__ === parent(ctypes).Object.prototype);
do_check_true(ctypes.CData.prototype.hasOwnProperty("constructor"));
do_check_true(ctypes.CData.prototype.constructor === ctypes.CData);
@ -303,12 +303,12 @@ function run_Int64_tests() {
do_check_class(ctypes.Int64, "Function");
do_check_class(ctypes.Int64.prototype, "Int64");
do_check_true(ctypes.Int64.__parent__ === ctypes);
do_check_true(ctypes.Int64.__proto__ === ctypes.__parent__.Function.prototype);
do_check_true(parent(ctypes.Int64) === ctypes);
do_check_true(ctypes.Int64.__proto__ === parent(ctypes).Function.prototype);
do_check_true(ctypes.Int64.hasOwnProperty("prototype"));
do_check_true(ctypes.Int64.prototype.__parent__ === ctypes);
do_check_true(ctypes.Int64.prototype.__proto__ === ctypes.__parent__.Object.prototype);
do_check_true(parent(ctypes.Int64.prototype) === ctypes);
do_check_true(ctypes.Int64.prototype.__proto__ === parent(ctypes).Object.prototype);
do_check_true(ctypes.Int64.prototype.hasOwnProperty("constructor"));
do_check_true(ctypes.Int64.prototype.constructor === ctypes.Int64);
@ -326,7 +326,7 @@ function run_Int64_tests() {
do_check_throws(function() { ctypes.Int64.prototype.toSource(); }, Error);
let i = ctypes.Int64(0);
do_check_true(i.__parent__ === ctypes);
do_check_true(parent(i) === ctypes);
do_check_true(i.__proto__ === ctypes.Int64.prototype);
do_check_true(i instanceof ctypes.Int64);
@ -480,12 +480,12 @@ function run_UInt64_tests() {
do_check_class(ctypes.UInt64, "Function");
do_check_class(ctypes.UInt64.prototype, "UInt64");
do_check_true(ctypes.UInt64.__parent__ === ctypes);
do_check_true(ctypes.UInt64.__proto__ === ctypes.__parent__.Function.prototype);
do_check_true(parent(ctypes.UInt64) === ctypes);
do_check_true(ctypes.UInt64.__proto__ === parent(ctypes).Function.prototype);
do_check_true(ctypes.UInt64.hasOwnProperty("prototype"));
do_check_true(ctypes.UInt64.prototype.__parent__ === ctypes);
do_check_true(ctypes.UInt64.prototype.__proto__ === ctypes.__parent__.Object.prototype);
do_check_true(parent(ctypes.UInt64.prototype) === ctypes);
do_check_true(ctypes.UInt64.prototype.__proto__ === parent(ctypes).Object.prototype);
do_check_true(ctypes.UInt64.prototype.hasOwnProperty("constructor"));
do_check_true(ctypes.UInt64.prototype.constructor === ctypes.UInt64);
@ -503,7 +503,7 @@ function run_UInt64_tests() {
do_check_throws(function() { ctypes.UInt64.prototype.toSource(); }, Error);
let i = ctypes.UInt64(0);
do_check_true(i.__parent__ === ctypes);
do_check_true(parent(i) === ctypes);
do_check_true(i.__proto__ === ctypes.UInt64.prototype);
do_check_true(i instanceof ctypes.UInt64);
@ -720,11 +720,11 @@ function run_basic_class_tests(t)
do_check_class(t, "CType");
do_check_class(t.prototype, "CData");
do_check_true(t.__parent__ === ctypes);
do_check_true(parent(t) === ctypes);
do_check_true(t.__proto__ === ctypes.CType.prototype);
do_check_true(t instanceof ctypes.CType);
do_check_true(t.prototype.__parent__ === ctypes);
do_check_true(parent(t.prototype) === ctypes);
do_check_true(t.prototype.__proto__ === ctypes.CData.prototype);
do_check_true(t.prototype instanceof ctypes.CData);
do_check_true(t.prototype.constructor === t);
@ -740,7 +740,7 @@ function run_basic_class_tests(t)
// Test that an instance 'd' of 't' is a CData.
let d = t();
do_check_class(d, "CData");
do_check_true(d.__parent__ === ctypes);
do_check_true(parent(d) === ctypes);
do_check_true(d.__proto__ === t.prototype);
do_check_true(d instanceof t);
do_check_true(d.constructor === t);
@ -1265,11 +1265,11 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance
do_check_class(c, "Function");
do_check_class(c.prototype, "CType");
do_check_true(c.__parent__ === ctypes);
do_check_true(c.__proto__ === ctypes.__parent__.Function.prototype);
do_check_true(c instanceof ctypes.__parent__.Function);
do_check_true(parent(c) === ctypes);
do_check_true(c.__proto__ === parent(ctypes).Function.prototype);
do_check_true(c instanceof parent(ctypes).Function);
do_check_true(c.prototype.__parent__ === ctypes);
do_check_true(parent(c.prototype) === ctypes);
do_check_true(c.prototype.__proto__ === ctypes.CType.prototype);
do_check_true(c.prototype instanceof ctypes.CType);
do_check_true(c.prototype.constructor === c);
@ -1291,18 +1291,18 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance
do_check_class(t, "CType");
do_check_class(t.prototype, "CData");
do_check_true(t.__parent__ === ctypes);
do_check_true(parent(t) === ctypes);
do_check_true(t.__proto__ === c.prototype);
do_check_true(t instanceof c);
do_check_true(t.prototype.__parent__ === ctypes);
do_check_true(parent(t.prototype) === ctypes);
do_check_class(t.prototype.__proto__, "CData");
// 't.prototype.__proto__' is the common ancestor of all types constructed
// from 'c'; while not available from 'c' directly, it should be identically
// equal to 't2.prototype.__proto__' where 't2' is a different CType
// constructed from 'c'.
do_check_true(t.prototype.__proto__ === t2.prototype.__proto__);
do_check_true(t.prototype.__proto__.__parent__ === ctypes);
do_check_true(parent(t.prototype.__proto__) === ctypes);
do_check_true(t.prototype.__proto__.__proto__ === ctypes.CData.prototype);
do_check_true(t.prototype instanceof ctypes.CData);
do_check_true(t.prototype.constructor === t);
@ -1337,7 +1337,7 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance
if (t.__proto__ != ctypes.FunctionType.prototype) {
let d = t();
do_check_class(d, "CData");
do_check_true(d.__parent__ === ctypes);
do_check_true(parent(d) === ctypes);
do_check_true(d.__proto__ === t.prototype);
do_check_true(d instanceof t);
do_check_true(d.constructor === t);

View File

@ -18,11 +18,17 @@ mochitest framework.
<script class="testbody" type="text/javascript">
<![CDATA[
function getParent(obj) {
return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.getParent(obj);
}
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var Cc = Components.classes;
var Ci = Components.interfaces;
var table = Cc["@mozilla.org/url-classifier/table;1?type=url"].createInstance();
var componentScope = table.wrappedJSObject.__parent__;
var componentScope = getParent(table.wrappedJSObject);
ok(!!componentScope, "unable to get wrapped js object");
////// Test PROT_EnchashDecrypter methods //////