Back out 570dd369e02a, bc777c65c5ca and 12a483042e9a to fix bustage

This commit is contained in:
Peter Van der Beken 2012-01-27 15:34:30 +01:00
parent a315c8f9b9
commit 17cd65acea
6 changed files with 32 additions and 193 deletions

View File

@ -1,14 +0,0 @@
<!DOCTYPE html>
<script>
var collection = document.images;
var other = document.embeds;
var options = document.createElement("select").options;
collection.toString;
options.selectedIndex;
Object.getPrototypeOf(collection).item = {};
other.toString;
collection.toString;
options.selectedIndex;
options.toString;
</script>

View File

@ -1,16 +0,0 @@
<!DOCTYPE html>
<script>
var collection = document.images;
var other = document.embeds;
var options = document.createElement("select").options;
collection.toString;
options.selectedIndex;
Object.defineProperty(Object.getPrototypeOf(collection),
"item",
{ value: {}, enumerable: true, configurable: true });
other.toString;
collection.toString;
options.selectedIndex;
options.toString;
</script>

View File

@ -30,8 +30,6 @@ load 637116.html
load 666869.html
load 675621-1.html
load 693894.html
load 693811-1.html
load 693811-2.html
load 695867.html
load 697643.html
load 706283-1.html

View File

@ -64,8 +64,6 @@ static jsid s_prototype_id = JSID_VOID;
static jsid s_length_id = JSID_VOID;
static jsid s_VOID_id = JSID_VOID;
bool
DefineStaticJSVal(JSContext *cx, jsid &id, const char *string)
{
@ -226,39 +224,6 @@ Unwrap(JSContext *cx, jsval v, NoType **ppArg, nsISupports **ppArgRef, jsval *vp
}
// Because we use proxies for wrapping DOM list objects we don't get the benefits of the property
// cache. To improve performance when using a property that lives on the prototype chain we
// implemented a cheap caching mechanism. Every DOM list proxy object stores a pointer to a shape
// in an extra slot. The first time we access a property on the object that lives on the prototype
// we check if all the DOM properties on the prototype chain are the real DOM properties and in
// that case we store a pointer to the shape of the object's prototype in the extra slot. From
// then on, every time we access a DOM property that lives on the prototype we check that the
// shape of the prototype is still identical to the cached shape and we do a fast lookup of the
// property. If the shape has changed, we recheck all the DOM properties on the prototype chain
// and we update the shape pointer if they are still the real DOM properties. This mechanism
// covers addition/removal of properties, changes in getters/setters, changes in the prototype
// chain, ... It does not cover changes in the values of the properties. For those we store an
// enum value in a reserved slot in every DOM prototype object. The value starts off as USE_CACHE.
// If a property of a DOM prototype object is set to a different value, we set the value to
// CHECK_CACHE. The next time we try to access the value of a property on that DOM prototype
// object we check if all the DOM properties on that DOM prototype object still match the real DOM
// properties. If they do we set the value to USE_CACHE again, if they're not we set the value to
// DONT_USE_CACHE. If the value is USE_CACHE we do the fast lookup.
template<class LC>
typename ListBase<LC>::Properties ListBase<LC>::sProtoProperties[] = {
{ s_VOID_id, NULL, NULL }
};
template<class LC>
size_t ListBase<LC>::sProtoPropertiesCount = 0;
template<class LC>
typename ListBase<LC>::Methods ListBase<LC>::sProtoMethods[] = {
{ s_VOID_id, NULL, 0 }
};
template<class LC>
size_t ListBase<LC>::sProtoMethodsCount = 0;
template<class LC>
ListBase<LC> ListBase<LC>::instance;
@ -306,27 +271,19 @@ ListBase<LC>::setProtoShape(JSObject *obj, js::Shape *shape)
js::SetProxyExtra(obj, JSPROXYSLOT_PROTOSHAPE, PrivateValue(shape));
}
static JSBool
UnwrapSecurityWrapper(JSContext *cx, JSObject *obj, JSObject *callee, JSObject **unwrapped)
{
JS_ASSERT(XPCWrapper::IsSecurityWrapper(obj));
if (callee && JS_GetGlobalForObject(cx, obj) == JS_GetGlobalForObject(cx, callee)) {
*unwrapped = js::UnwrapObject(obj);
} else {
*unwrapped = XPCWrapper::Unwrap(cx, obj);
if (!*unwrapped)
return Throw(cx, NS_ERROR_XPC_SECURITY_MANAGER_VETO);
}
return true;
}
template<class LC>
bool
ListBase<LC>::instanceIsListObject(JSContext *cx, JSObject *obj, JSObject *callee)
{
if (XPCWrapper::IsSecurityWrapper(obj) && !UnwrapSecurityWrapper(cx, obj, callee, &obj))
return false;
if (XPCWrapper::IsSecurityWrapper(obj)) {
if (callee && JS_GetGlobalForObject(cx, obj) == JS_GetGlobalForObject(cx, callee)) {
obj = js::UnwrapObject(obj);
} else {
obj = XPCWrapper::Unwrap(cx, obj);
if (!obj)
return Throw(cx, NS_ERROR_XPC_SECURITY_MANAGER_VETO);
}
}
if (!objIsList(obj)) {
// FIXME: Throw a proper DOM exception.
@ -447,38 +404,6 @@ ListBase<LC>::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, bool *en
return getPrototype(cx, scope);
}
enum {
USE_CACHE = 0,
CHECK_CACHE = 1,
DONT_USE_CACHE = 2
};
static JSBool
InvalidateProtoShape_add(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
if (JSID_IS_STRING(id))
js::SetReservedSlot(obj, 0, PrivateUint32Value(CHECK_CACHE));
return JS_TRUE;
}
static JSBool
InvalidateProtoShape_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
{
return InvalidateProtoShape_add(cx, obj, id, vp);
}
js::Class sInterfacePrototypeClass = {
"Object",
JSCLASS_HAS_RESERVED_SLOTS(1),
InvalidateProtoShape_add, /* addProperty */
JS_PropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
InvalidateProtoShape_set, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub
};
template<class LC>
JSObject *
ListBase<LC>::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope)
@ -499,11 +424,11 @@ ListBase<LC>::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope)
return NULL;
JSObject *global = scope->GetGlobalJSObject();
interfacePrototype = JS_NewObject(cx, Jsvalify(&sInterfacePrototypeClass), proto, global);
interfacePrototype = JS_NewObject(cx, NULL, proto, global);
if (!interfacePrototype)
return NULL;
for (size_t n = 0; n < sProtoPropertiesCount; ++n) {
for (size_t n = 0; n < ArrayLength(sProtoProperties); ++n) {
JS_ASSERT(sProtoProperties[n].getter);
jsid id = sProtoProperties[n].id;
uintN attrs = JSPROP_ENUMERATE | JSPROP_SHARED;
@ -514,7 +439,7 @@ ListBase<LC>::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope)
return NULL;
}
for (size_t n = 0; n < sProtoMethodsCount; ++n) {
for (size_t n = 0; n < ArrayLength(sProtoMethods); ++n) {
jsid id = sProtoMethods[n].id;
JSFunction *fun = JS_NewFunctionById(cx, sProtoMethods[n].native, sProtoMethods[n].nargs,
0, js::GetObjectParent(interfacePrototype), id);
@ -540,10 +465,6 @@ ListBase<LC>::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope)
NULL, 0))
return NULL;
// This needs to happen after we've set all our own properties on interfacePrototype, to
// overwrite the value set by InvalidateProtoShape_add when we set our own properties.
js::SetReservedSlot(interfacePrototype, 0, PrivateUint32Value(USE_CACHE));
if (!cache.Put(sInterfaceClass.name, interfacePrototype))
return NULL;
@ -918,48 +839,32 @@ ListBase<LC>::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
template<class LC>
bool
ListBase<LC>::protoIsClean(JSContext *cx, JSObject *proto, bool *isClean)
ListBase<LC>::shouldCacheProtoShape(JSContext *cx, JSObject *proto, bool *shouldCache)
{
JSPropertyDescriptor desc;
for (size_t n = 0; n < sProtoPropertiesCount; ++n) {
for (size_t n = 0; n < ArrayLength(sProtoProperties); ++n) {
jsid id = sProtoProperties[n].id;
if (!JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, &desc))
return false;
JSStrictPropertyOp setter =
sProtoProperties[n].setter ? sProtoProperties[n].setter : InvalidateProtoShape_set;
if (desc.obj != proto || desc.getter != sProtoProperties[n].getter ||
desc.setter != setter) {
*isClean = false;
desc.setter != sProtoProperties[n].setter) {
*shouldCache = false;
return true;
}
}
for (size_t n = 0; n < sProtoMethodsCount; ++n) {
for (size_t n = 0; n < ArrayLength(sProtoMethods); ++n) {
jsid id = sProtoMethods[n].id;
if (!JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, &desc))
return false;
if (desc.obj != proto || desc.getter || JSVAL_IS_PRIMITIVE(desc.value) ||
n >= js::GetObjectSlotSpan(proto) || js::GetObjectSlot(proto, n + 1) != desc.value ||
n >= js::GetObjectSlotSpan(proto) || js::GetObjectSlot(proto, n) != desc.value ||
!JS_IsNativeFunction(JSVAL_TO_OBJECT(desc.value), sProtoMethods[n].native)) {
*isClean = false;
*shouldCache = false;
return true;
}
}
*isClean = true;
return true;
}
template<class LC>
bool
ListBase<LC>::shouldCacheProtoShape(JSContext *cx, JSObject *proto, bool *shouldCache)
{
bool ok = protoIsClean(cx, proto, shouldCache);
if (!ok || !*shouldCache)
return ok;
js::SetReservedSlot(proto, 0, PrivateUint32Value(USE_CACHE));
JSObject *protoProto = js::GetObjectProto(proto);
if (!protoProto) {
*shouldCache = false;
@ -975,7 +880,7 @@ ListBase<LC>::resolveNativeName(JSContext *cx, JSObject *proxy, jsid id, JSPrope
{
JS_ASSERT(xpc::WrapperFactory::IsXrayWrapper(proxy));
for (size_t n = 0; n < sProtoPropertiesCount; ++n) {
for (size_t n = 0; n < ArrayLength(sProtoProperties); ++n) {
if (id == sProtoProperties[n].id) {
desc->attrs = JSPROP_ENUMERATE | JSPROP_SHARED;
if (!sProtoProperties[n].setter)
@ -987,7 +892,7 @@ ListBase<LC>::resolveNativeName(JSContext *cx, JSObject *proxy, jsid id, JSPrope
}
}
for (size_t n = 0; n < sProtoMethodsCount; ++n) {
for (size_t n = 0; n < ArrayLength(sProtoMethods); ++n) {
if (id == sProtoMethods[n].id) {
JSFunction *fun = JS_NewFunctionById(cx, sProtoMethods[n].native,
sProtoMethods[n].nargs, 0, proxy, id);
@ -1010,28 +915,12 @@ template<class LC>
bool
ListBase<LC>::nativeGet(JSContext *cx, JSObject *proxy, JSObject *proto, jsid id, bool *found, Value *vp)
{
uint32_t cache = js::GetReservedSlot(proto, 0).toPrivateUint32();
if (cache == CHECK_CACHE) {
bool isClean;
if (!protoIsClean(cx, proto, &isClean))
return false;
if (!isClean) {
js::SetReservedSlot(proto, 0, PrivateUint32Value(DONT_USE_CACHE));
return true;
}
js::SetReservedSlot(proto, 0, PrivateUint32Value(USE_CACHE));
}
else if (cache == DONT_USE_CACHE) {
return true;
}
else {
#ifdef DEBUG
bool isClean;
JS_ASSERT(protoIsClean(cx, proto, &isClean) && isClean);
bool shouldCache;
JS_ASSERT(shouldCacheProtoShape(cx, proto, &shouldCache) && shouldCache);
#endif
}
for (size_t n = 0; n < sProtoPropertiesCount; ++n) {
for (size_t n = 0; n < ArrayLength(sProtoProperties); ++n) {
if (id == sProtoProperties[n].id) {
*found = true;
if (!vp)
@ -1040,13 +929,13 @@ ListBase<LC>::nativeGet(JSContext *cx, JSObject *proxy, JSObject *proto, jsid id
return sProtoProperties[n].getter(cx, proxy, id, vp);
}
}
for (size_t n = 0; n < sProtoMethodsCount; ++n) {
for (size_t n = 0; n < ArrayLength(sProtoMethods); ++n) {
if (id == sProtoMethods[n].id) {
*found = true;
if (!vp)
return true;
*vp = js::GetObjectSlot(proto, n + 1);
*vp = js::GetObjectSlot(proto, n);
JS_ASSERT(JS_IsNativeFunction(&vp->toObject(), sProtoMethods[n].native));
return true;
}

View File

@ -183,9 +183,7 @@ private:
};
static Properties sProtoProperties[];
static size_t sProtoPropertiesCount;
static Methods sProtoMethods[];
static size_t sProtoMethodsCount;
static JSObject *ensureExpandoObject(JSContext *cx, JSObject *obj);
@ -246,15 +244,14 @@ public:
static bool objIsList(JSObject *obj) {
return js::IsProxy(obj) && proxyHandlerIsList(js::GetProxyHandler(obj));
}
static inline bool instanceIsListObject(JSContext *cx, JSObject *obj, JSObject *callee);
static bool instanceIsListObject(JSContext *cx, JSObject *obj, JSObject *callee);
virtual bool isInstanceOf(JSObject *prototype)
{
return js::GetObjectClass(prototype) == &sInterfaceClass;
}
static inline ListType *getListObject(JSObject *obj);
static ListType *getListObject(JSObject *obj);
static JSObject *getPrototype(JSContext *cx, XPCWrappedNativeScope *scope);
static inline bool protoIsClean(JSContext *cx, JSObject *proto, bool *isClean);
static bool shouldCacheProtoShape(JSContext *cx, JSObject *proto, bool *shouldCache);
static bool resolveNativeName(JSContext *cx, JSObject *proxy, jsid id,
JSPropertyDescriptor *desc);

View File

@ -443,7 +443,7 @@ listTemplate = (
" JS_EnumerateStub,\n"
" JS_ResolveStub,\n"
" JS_ConvertStub,\n"
" JS_FinalizeStub,\n"
" NULL, /* finalize */\n"
" NULL, /* reserved0 */\n"
" NULL, /* checkAccess */\n"
" NULL, /* call */\n"
@ -527,27 +527,16 @@ nameSetterTemplate = (
"}\n"
"\n")
propertiesTemplate = (
listTemplateFooter = (
"template<>\n"
"${name}Wrapper::Properties ${name}Wrapper::sProtoProperties[] = {\n"
"${properties}\n"
"};\n"
"\n"
"template<>\n"
"size_t ${name}Wrapper::sProtoPropertiesCount = ArrayLength(${name}Wrapper::sProtoProperties);\n"
"\n")
methodsTemplate = (
"template<>\n"
"\n""template<>\n"
"${name}Wrapper::Methods ${name}Wrapper::sProtoMethods[] = {\n"
"${methods}\n"
"};\n"
"\n"
"template<>\n"
"size_t ${name}Wrapper::sProtoMethodsCount = ArrayLength(${name}Wrapper::sProtoMethods);\n"
"\n")
listTemplateFooter = (
"template class ListBase<${name}Class>;\n"
"\n"
"JSObject*\n"
@ -729,11 +718,7 @@ def writeStubFile(filename, config, interfaces):
else:
propertiesList.append(writeAttrStubs(f, clazz.name, member))
if len(propertiesList) > 0:
f.write(string.Template(propertiesTemplate).substitute(clazz, properties=",\n".join(propertiesList)))
if len(methodsList) > 0:
f.write(string.Template(methodsTemplate).substitute(clazz, methods=",\n".join(methodsList)))
f.write(string.Template(listTemplateFooter).substitute(clazz))
f.write(string.Template(listTemplateFooter).substitute(clazz, methods=",\n".join(methodsList), properties=",\n".join(propertiesList)))
f.write("// Register prototypes\n\n")