Bug 603201 - Make HasPropertyOnPrototype fallible. r=peterv

This commit is contained in:
Jeff Walden 2015-01-02 14:02:36 -06:00
parent 7d06ab3c2d
commit 7328185745
4 changed files with 89 additions and 36 deletions

View File

@ -83,8 +83,11 @@ WindowNamedPropertiesHandler::getOwnPropDescriptor(JSContext* aCx,
return true; return true;
} }
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, aProxy)); bool hasOnPrototype;
if (HasPropertyOnPrototype(aCx, aProxy, aId)) { if (!HasPropertyOnPrototype(aCx, aProxy, aId, &hasOnPrototype)) {
return false;
}
if (hasOnPrototype) {
return true; return true;
} }
@ -94,6 +97,7 @@ WindowNamedPropertiesHandler::getOwnPropDescriptor(JSContext* aCx,
} }
// Grab the DOM window. // Grab the DOM window.
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, aProxy));
nsGlobalWindow* win = xpc::WindowOrNull(global); nsGlobalWindow* win = xpc::WindowOrNull(global);
if (win->Length() > 0) { if (win->Length() > 0) {
nsCOMPtr<nsIDOMWindow> childWin = win->GetChildWindow(str); nsCOMPtr<nsIDOMWindow> childWin = win->GetChildWindow(str);

View File

@ -1613,7 +1613,7 @@ NativePropertyHooks sWorkerNativePropertyHooks = {
bool bool
GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy, GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id, bool* found, JS::Handle<jsid> id, bool* found,
JS::Value* vp) JS::MutableHandle<JS::Value> vp)
{ {
JS::Rooted<JSObject*> proto(cx); JS::Rooted<JSObject*> proto(cx);
if (!js::GetObjectProto(cx, proxy, &proto)) { if (!js::GetObjectProto(cx, proxy, &proto)) {
@ -1624,33 +1624,31 @@ GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
return true; return true;
} }
bool hasProp; if (!JS_HasPropertyById(cx, proto, id, found)) {
if (!JS_HasPropertyById(cx, proto, id, &hasProp)) {
return false; return false;
} }
*found = hasProp; if (!*found) {
if (!hasProp || !vp) {
return true; return true;
} }
JS::Rooted<JS::Value> value(cx); return JS_ForwardGetPropertyTo(cx, proto, id, proxy, vp);
if (!JS_ForwardGetPropertyTo(cx, proto, id, proxy, &value)) {
return false;
}
*vp = value;
return true;
} }
bool bool
HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy, HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id) JS::Handle<jsid> id, bool* has)
{ {
bool found; JS::Rooted<JSObject*> proto(cx);
// We ignore an error from GetPropertyOnPrototype. We pass nullptr if (!js::GetObjectProto(cx, proxy, &proto)) {
// for vp so that GetPropertyOnPrototype won't actually do a get. return false;
return !GetPropertyOnPrototype(cx, proxy, id, &found, nullptr) || found; }
if (!proto) {
*has = false;
return true;
}
return JS_HasPropertyById(cx, proto, id, has);
} }
bool bool
@ -1670,7 +1668,16 @@ AppendNamedPropertyIds(JSContext* cx, JS::Handle<JSObject*> proxy,
return false; return false;
} }
if (shadowPrototypeProperties || !HasPropertyOnPrototype(cx, proxy, id)) { bool shouldAppend = shadowPrototypeProperties;
if (!shouldAppend) {
bool has;
if (!HasPropertyOnPrototype(cx, proxy, id, &has)) {
return false;
}
shouldAppend = !has;
}
if (shouldAppend) {
if (!props.append(id)) { if (!props.append(id)) {
return false; return false;
} }

View File

@ -1810,16 +1810,15 @@ ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
bool bool
ThrowConstructorWithoutNew(JSContext* cx, const char* name); ThrowConstructorWithoutNew(JSContext* cx, const char* name);
// vp is allowed to be null; in that case no get will be attempted,
// and *found will simply indicate whether the property exists.
bool bool
GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy, GetPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id, bool* found, JS::Handle<jsid> id, bool* found,
JS::Value* vp); JS::MutableHandle<JS::Value> vp);
//
bool bool
HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy, HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id); JS::Handle<jsid> id, bool* has);
// Append the property names in "names" to "props". If // Append the property names in "names" to "props". If

View File

@ -10104,15 +10104,41 @@ class CGDOMJSProxyHandler_getOwnPropDescriptor(ClassMethod):
"return true;\n" % (readonly, enumerable)) "return true;\n" % (readonly, enumerable))
templateValues = {'jsvalRef': 'desc.value()', 'jsvalHandle': 'desc.value()', templateValues = {'jsvalRef': 'desc.value()', 'jsvalHandle': 'desc.value()',
'obj': 'proxy', 'successCode': fillDescriptor} 'obj': 'proxy', 'successCode': fillDescriptor}
condition = "!HasPropertyOnPrototype(cx, proxy, id)"
computeCondition = dedent("""
bool hasOnProto;
if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
return false;
}
callNamedGetter = !hasOnProto;
""")
if self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'): if self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
condition = "(!isXray || %s)" % condition computeCondition = fill("""
condition = "!ignoreNamedProps && " + condition if (!isXray) {
callNamedGetter = true;
} else {
$*{hasOnProto}
}
""",
hasOnProto=computeCondition)
outerCondition = "!ignoreNamedProps"
if self.descriptor.supportsIndexedProperties(): if self.descriptor.supportsIndexedProperties():
condition = "!IsArrayIndex(index) && " + condition outerCondition = "!IsArrayIndex(index) && " + outerCondition
namedGet = (CGIfWrapper(CGProxyNamedGetter(self.descriptor, templateValues),
condition).define() + namedGet = fill("""
"\n") bool callNamedGetter = false;
if (${outerCondition}) {
$*{computeCondition}
}
if (callNamedGetter) {
$*{namedGetCode}
}
""",
outerCondition=outerCondition,
computeCondition=computeCondition,
namedGetCode=CGProxyNamedGetter(self.descriptor, templateValues).define())
namedGet += "\n"
else: else:
namedGet = "" namedGet = ""
@ -10345,8 +10371,16 @@ class CGDOMJSProxyHandler_delete(ClassMethod):
""", """,
namedBody=namedBody) namedBody=namedBody)
if not self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'): if not self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
delete = CGIfWrapper(CGGeneric(delete), delete = fill("""
"!HasPropertyOnPrototype(cx, proxy, id)").define() bool hasOnProto;
if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
return false;
}
if (!hasOnProto) {
$*{delete}
}
""",
delete=delete)
delete += dedent(""" delete += dedent("""
@ -10485,8 +10519,17 @@ class CGDOMJSProxyHandler_hasOwn(ClassMethod):
""", """,
presenceChecker=CGProxyNamedPresenceChecker(self.descriptor, foundVar="found").define()) presenceChecker=CGProxyNamedPresenceChecker(self.descriptor, foundVar="found").define())
if not self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'): if not self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
named = CGIfWrapper(CGGeneric(named + "return true;\n"), named = fill("""
"!HasPropertyOnPrototype(cx, proxy, id)").define() bool hasOnProto;
if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
return false;
}
if (!hasOnProto) {
$*{protoLacksProperty}
return true;
}
""",
protoLacksProperty=named)
named += "*bp = false;\n" named += "*bp = false;\n"
else: else:
named += "\n" named += "\n"
@ -10593,7 +10636,7 @@ class CGDOMJSProxyHandler_get(ClassMethod):
getOnPrototype = dedent(""" getOnPrototype = dedent("""
bool foundOnPrototype; bool foundOnPrototype;
if (!GetPropertyOnPrototype(cx, proxy, id, &foundOnPrototype, vp.address())) { if (!GetPropertyOnPrototype(cx, proxy, id, &foundOnPrototype, vp)) {
return false; return false;
} }