зеркало из https://github.com/mozilla/gecko-dev.git
Back out 570dd369e02a, bc777c65c5ca and 12a483042e9a to fix bustage
This commit is contained in:
Родитель
56a33403d0
Коммит
fd97a8a392
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче