Bug 1103368, part 2 - Ban stub getter/setter arguments to js::baseops::Define{Property,Generic,Element}, DefineNativeProperty, and DefinePropertyOrElement. r=bhackett.

--HG--
extra : rebase_source : 1b8524aebf85aa27fa9542b8001cae489888e887
This commit is contained in:
Jason Orendorff 2014-11-21 21:07:13 -06:00
parent d72b08b11e
commit 3414c5c5ff
12 changed files with 88 additions and 77 deletions

View File

@ -2275,10 +2275,14 @@ IteratorResultShape(ExclusiveContext *cx, BytecodeEmitter *bce, unsigned *shape)
Rooted<jsid> done_id(cx, AtomToId(cx->names().done));
if (!DefineNativeProperty(cx, obj, value_id, UndefinedHandleValue, nullptr, nullptr,
JSPROP_ENUMERATE))
{
return false;
}
if (!DefineNativeProperty(cx, obj, done_id, UndefinedHandleValue, nullptr, nullptr,
JSPROP_ENUMERATE))
{
return false;
}
ObjectBox *objbox = bce->parser->newObjectBox(obj);
if (!objbox)
@ -6574,8 +6578,8 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
MOZ_ASSERT(!obj->inDictionaryMode());
Rooted<jsid> id(cx, AtomToId(key->pn_atom));
RootedValue undefinedValue(cx, UndefinedValue());
if (!DefineNativeProperty(cx, obj, id, undefinedValue, nullptr,
nullptr, JSPROP_ENUMERATE))
if (!DefineNativeProperty(cx, obj, id, undefinedValue, nullptr, nullptr,
JSPROP_ENUMERATE))
{
return false;
}

View File

@ -3013,7 +3013,7 @@ FinishDateClassInit(JSContext *cx, HandleObject ctor, HandleObject proto)
RootedId toGMTStringId(cx, NameToId(cx->names().toGMTString));
return baseops::GetProperty(cx, proto.as<DateObject>(), toUTCStringId, &toUTCStringFun) &&
baseops::DefineGeneric(cx, proto.as<DateObject>(), toGMTStringId, toUTCStringFun,
JS_PropertyStub, JS_StrictPropertyStub, 0);
nullptr, nullptr, 0);
}
const Class DateObject::class_ = {

View File

@ -499,7 +499,7 @@ js::fun_resolve(JSContext *cx, HandleObject obj, HandleId id, bool *resolvedp)
v.setString(fun->atom() == nullptr ? cx->runtime()->emptyString : fun->atom());
}
if (!DefineNativeProperty(cx, fun, id, v, JS_PropertyStub, JS_StrictPropertyStub,
if (!DefineNativeProperty(cx, fun, id, v, nullptr, nullptr,
JSPROP_PERMANENT | JSPROP_READONLY)) {
return false;
}

View File

@ -1212,11 +1212,9 @@ js_InitNumberClass(JSContext *cx, HandleObject obj)
RootedValue valueInfinity(cx, cx->runtime()->positiveInfinityValue);
/* ES5 15.1.1.1, 15.1.1.2 */
if (!DefineNativeProperty(cx, global, cx->names().NaN, valueNaN,
JS_PropertyStub, JS_StrictPropertyStub,
if (!DefineNativeProperty(cx, global, cx->names().NaN, valueNaN, nullptr, nullptr,
JSPROP_PERMANENT | JSPROP_READONLY) ||
!DefineNativeProperty(cx, global, cx->names().Infinity, valueInfinity,
JS_PropertyStub, JS_StrictPropertyStub,
!DefineNativeProperty(cx, global, cx->names().Infinity, valueInfinity, nullptr, nullptr,
JSPROP_PERMANENT | JSPROP_READONLY))
{
return nullptr;

View File

@ -613,9 +613,7 @@ DefinePropertyOnObject(JSContext *cx, HandleNativeObject obj, HandleId id, const
if (desc.isGenericDescriptor() || desc.isDataDescriptor()) {
MOZ_ASSERT(!obj->getOps()->defineProperty);
RootedValue v(cx, desc.hasValue() ? desc.value() : UndefinedValue());
return baseops::DefineGeneric(cx, obj, id, v,
JS_PropertyStub, JS_StrictPropertyStub,
desc.attributes());
return baseops::DefineGeneric(cx, obj, id, v, nullptr, nullptr, desc.attributes());
}
MOZ_ASSERT(desc.isAccessorDescriptor());
@ -822,8 +820,8 @@ DefinePropertyOnObject(JSContext *cx, HandleNativeObject obj, HandleId id, const
changed |= JSPROP_ENUMERATE;
attrs = (shapeAttributes & ~changed) | (desc.attributes() & changed);
getter = IsImplicitDenseOrTypedArrayElement(shape) ? JS_PropertyStub : shape->getter();
setter = IsImplicitDenseOrTypedArrayElement(shape) ? JS_StrictPropertyStub : shape->setter();
getter = IsImplicitDenseOrTypedArrayElement(shape) ? nullptr : shape->getter();
setter = IsImplicitDenseOrTypedArrayElement(shape) ? nullptr : shape->setter();
} else if (desc.isDataDescriptor()) {
unsigned unchanged = 0;
if (!desc.hasConfigurable())
@ -837,8 +835,8 @@ DefinePropertyOnObject(JSContext *cx, HandleNativeObject obj, HandleId id, const
if (desc.hasValue())
v = desc.value();
attrs = (desc.attributes() & ~unchanged) | (shapeAttributes & unchanged);
getter = JS_PropertyStub;
setter = JS_StrictPropertyStub;
getter = nullptr;
setter = nullptr;
} else {
MOZ_ASSERT(desc.isAccessorDescriptor());
@ -858,14 +856,14 @@ DefinePropertyOnObject(JSContext *cx, HandleNativeObject obj, HandleId id, const
getter = desc.getter();
} else {
getter = (shapeHasDefaultGetter && !shapeHasGetterValue)
? JS_PropertyStub
? nullptr
: shape->getter();
}
if (desc.hasSet()) {
setter = desc.setter();
} else {
setter = (shapeHasDefaultSetter && !shapeHasSetterValue)
? JS_StrictPropertyStub
? nullptr
: shape->setter();
}
}
@ -2119,8 +2117,11 @@ js::XDRObjectLiteral(XDRState<mode> *xdr, MutableHandleNativeObject obj)
return false;
if (mode == XDR_DECODE) {
if (!DefineNativeProperty(cx, obj, id, tmpValue, NULL, NULL, JSPROP_ENUMERATE))
if (!DefineNativeProperty(cx, obj, id, tmpValue, nullptr, nullptr,
JSPROP_ENUMERATE))
{
return false;
}
}
}
@ -2893,6 +2894,15 @@ JSObject::defineGeneric(ExclusiveContext *cx, HandleObject obj,
return false;
return op(cx->asJSContext(), obj, id, value, getter, setter, attrs);
}
if (getter == nullptr)
getter = obj->getClass()->getProperty;
if (setter == nullptr)
setter = obj->getClass()->setProperty;
if (getter == JS_PropertyStub)
getter = nullptr;
if (setter == JS_StrictPropertyStub)
setter = nullptr;
return baseops::DefineGeneric(cx, obj.as<NativeObject>(), id, value, getter, setter, attrs);
}
@ -2916,6 +2926,15 @@ JSObject::defineElement(ExclusiveContext *cx, HandleObject obj,
return false;
return op(cx->asJSContext(), obj, index, value, getter, setter, attrs);
}
if (!getter)
getter = obj->getClass()->getProperty;
if (!setter)
setter = obj->getClass()->setProperty;
if (getter == JS_PropertyStub)
getter = nullptr;
if (setter == JS_StrictPropertyStub)
setter = nullptr;
return baseops::DefineElement(cx, obj.as<NativeObject>(), index, value, getter, setter, attrs);
}

View File

@ -668,11 +668,8 @@ js_Stringify(JSContext *cx, MutableHandleValue vp, JSObject *replacer_, Value sp
/* Step 10. */
RootedId emptyId(cx, NameToId(cx->names().empty));
if (!DefineNativeProperty(cx, wrapper, emptyId, vp, JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_ENUMERATE))
{
if (!DefineNativeProperty(cx, wrapper, emptyId, vp, nullptr, nullptr, JSPROP_ENUMERATE))
return false;
}
/* Step 11. */
StringifyContext scx(cx, sb, gap, replacer, propertyList);

View File

@ -346,12 +346,11 @@ ArgSetter(JSContext *cx, HandleObject obj, HandleId id, bool strict, MutableHand
}
/*
* For simplicity we use delete/define to replace the property with one
* backed by the default Object getter and setter. Note that we rely on
* args_delProperty to clear the corresponding reserved slot so the GC can
* collect its value. Note also that we must define the property instead
* of setting it in case the user has changed the prototype to an object
* that has a setter for this id.
* For simplicity we use delete/define to replace the property with a
* simple data property. Note that we rely on args_delProperty to clear the
* corresponding reserved slot so the GC can collect its value. Note also
* that we must define the property instead of setting it in case the user
* has changed the prototype to an object that has a setter for this id.
*/
bool succeeded;
return baseops::DeleteGeneric(cx, argsobj, id, &succeeded) &&
@ -462,10 +461,9 @@ StrictArgSetter(JSContext *cx, HandleObject obj, HandleId id, bool strict, Mutab
}
/*
* For simplicity we use delete/define to replace the property with one
* backed by the default Object getter and setter. Note that we rely on
* args_delProperty to clear the corresponding reserved slot so the GC can
* collect its value.
* For simplicity we use delete/define to replace the property with a
* simple data property. Note that we rely on args_delProperty to clear the
* corresponding reserved slot so the GC can collect its value.
*/
bool succeeded;
return baseops::DeleteGeneric(cx, argsobj, id, &succeeded) &&

View File

@ -1053,8 +1053,7 @@ Debugger::newCompletionValue(JSContext *cx, JSTrapStatus status, Value value_,
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx));
if (!obj ||
!wrapDebuggeeValue(cx, &value) ||
!DefineNativeProperty(cx, obj, key, value, JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_ENUMERATE))
!DefineNativeProperty(cx, obj, key, value, nullptr, nullptr, JSPROP_ENUMERATE))
{
return false;
}
@ -5426,8 +5425,7 @@ DebuggerFrame_getArguments(JSContext *cx, unsigned argc, Value *vp)
MOZ_ASSERT(frame.numActualArgs() <= 0x7fffffff);
unsigned fargc = frame.numActualArgs();
RootedValue fargcVal(cx, Int32Value(fargc));
if (!DefineNativeProperty(cx, argsobj, cx->names().length,
fargcVal, nullptr, nullptr,
if (!DefineNativeProperty(cx, argsobj, cx->names().length, fargcVal, nullptr, nullptr,
JSPROP_PERMANENT | JSPROP_READONLY))
{
return false;

View File

@ -606,10 +606,8 @@ JSONParserBase::createFinishedObject(PropertyVector &properties)
for (size_t i = 0; i < properties.length(); i++) {
propid = properties[i].id;
value = properties[i].value;
if (!DefineNativeProperty(cx, obj, propid, value, JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_ENUMERATE)) {
if (!DefineNativeProperty(cx, obj, propid, value, nullptr, nullptr, JSPROP_ENUMERATE))
return nullptr;
}
}
/*

View File

@ -624,6 +624,9 @@ DefineNativeProperty(ExclusiveContext *cx, HandleNativeObject obj,
PropertyName *name, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
RootedId id(cx, NameToId(name));
return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs);
}

View File

@ -1062,11 +1062,10 @@ NativeObject::addDataProperty(ExclusiveContext *cx, HandlePropertyName name,
template <ExecutionMode mode>
static inline bool
CallAddPropertyHook(typename ExecutionModeTraits<mode>::ExclusiveContextType cxArg,
const Class *clasp, HandleNativeObject obj, HandleShape shape,
HandleValue nominal)
HandleNativeObject obj, HandleShape shape, HandleValue nominal)
{
if (clasp->addProperty) {
MOZ_ASSERT(clasp->addProperty != JS_PropertyStub);
if (JSPropertyOp addProperty = obj->getClass()->addProperty) {
MOZ_ASSERT(addProperty != JS_PropertyStub);
if (mode == ParallelExecution)
return false;
@ -1079,7 +1078,7 @@ CallAddPropertyHook(typename ExecutionModeTraits<mode>::ExclusiveContextType cxA
RootedValue value(cx, nominal);
Rooted<jsid> id(cx, shape->propid());
if (!CallJSPropertyOp(cx->asJSContext(), clasp->addProperty, obj, id, &value)) {
if (!CallJSPropertyOp(cx->asJSContext(), addProperty, obj, id, &value)) {
obj->removeProperty(cx, shape->propid());
return false;
}
@ -1094,8 +1093,7 @@ CallAddPropertyHook(typename ExecutionModeTraits<mode>::ExclusiveContextType cxA
template <ExecutionMode mode>
static inline bool
CallAddPropertyHookDense(typename ExecutionModeTraits<mode>::ExclusiveContextType cxArg,
const Class *clasp, HandleNativeObject obj, uint32_t index,
HandleValue nominal)
HandleNativeObject obj, uint32_t index, HandleValue nominal)
{
/* Inline addProperty for array objects. */
if (obj->is<ArrayObject>()) {
@ -1114,8 +1112,8 @@ CallAddPropertyHookDense(typename ExecutionModeTraits<mode>::ExclusiveContextTyp
return true;
}
if (clasp->addProperty) {
MOZ_ASSERT(clasp->addProperty != JS_PropertyStub);
if (JSPropertyOp addProperty = obj->getClass()->addProperty) {
MOZ_ASSERT(addProperty != JS_PropertyStub);
if (mode == ParallelExecution)
return false;
@ -1131,7 +1129,7 @@ CallAddPropertyHookDense(typename ExecutionModeTraits<mode>::ExclusiveContextTyp
RootedValue value(cx, nominal);
Rooted<jsid> id(cx, INT_TO_JSID(index));
if (!CallJSPropertyOp(cx->asJSContext(), clasp->addProperty, obj, id, &value)) {
if (!CallJSPropertyOp(cx->asJSContext(), addProperty, obj, id, &value)) {
obj->setDenseElementHole(cx, index);
return false;
}
@ -1197,10 +1195,13 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
unsigned attrs, HandleValue value,
bool callSetterAfterwards, bool setterIsStrict)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
/* Use dense storage for new indexed properties where possible. */
if (JSID_IS_INT(id) &&
getter == JS_PropertyStub &&
setter == JS_StrictPropertyStub &&
!getter &&
!setter &&
attrs == JSPROP_ENUMERATE &&
(!obj->isIndexed() || !obj->containsPure(id)) &&
!IsAnyTypedArray(obj))
@ -1230,7 +1231,7 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
} else {
obj->setDenseElementWithType(cx->asExclusiveContext(), index, value);
}
return CallAddPropertyHookDense<mode>(cx, obj->getClass(), obj, index, value);
return CallAddPropertyHookDense<mode>(cx, obj, index, value);
}
}
@ -1261,11 +1262,6 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
}
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
if (getter == JS_PropertyStub)
getter = nullptr;
if (setter == JS_StrictPropertyStub)
setter = nullptr;
RootedShape shape(cx, NativeObject::putProperty<mode>(cx, obj, id, getter, setter,
SHAPE_INVALID_SLOT, attrs, 0));
if (!shape)
@ -1293,11 +1289,11 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
return false;
if (result == NativeObject::ED_OK) {
MOZ_ASSERT(!setter);
return CallAddPropertyHookDense<mode>(cx, obj->getClass(), obj, index, value);
return CallAddPropertyHookDense<mode>(cx, obj, index, value);
}
}
if (!CallAddPropertyHook<mode>(cx, obj->getClass(), obj, shape, value))
if (!CallAddPropertyHook<mode>(cx, obj, shape, value))
return false;
if (callSetterAfterwards && setter) {
@ -1426,6 +1422,8 @@ bool
js::DefineNativeProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
MOZ_ASSERT(!(attrs & JSPROP_PROPOP_ACCESSORS));
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
@ -1460,10 +1458,6 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
if (!CheckAccessorRedefinition(cx, obj, shape, getter, setter, id, attrs))
return false;
attrs = ApplyOrDefaultAttributes(attrs, shape);
if (getter == JS_PropertyStub)
getter = nullptr;
if (setter == JS_StrictPropertyStub)
setter = nullptr;
shape = NativeObject::changeProperty<SequentialExecution>(cx, obj, shape, attrs,
JSPROP_GETTER | JSPROP_SETTER,
(attrs & JSPROP_GETTER)
@ -1550,13 +1544,6 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
if (!PurgeScopeChain(cx, obj, id))
return false;
/* Use the object's class getter and setter by default. */
const Class *clasp = obj->getClass();
if (!getter && !(attrs & JSPROP_GETTER))
getter = clasp->getProperty;
if (!setter && !(attrs & JSPROP_SETTER))
setter = clasp->setProperty;
if (shouldDefine) {
// Handle the default cases here. Anyone that wanted to set non-default attributes has
// cleared the IGNORE flags by now. Since we can never get here with JSPROP_IGNORE_VALUE
@ -1570,7 +1557,7 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
JS_ALWAYS_TRUE(UpdateShapeTypeAndValue<SequentialExecution>(cx, obj, shape, updateValue));
return CallAddPropertyHook<SequentialExecution>(cx, clasp, obj, shape, updateValue);
return CallAddPropertyHook<SequentialExecution>(cx, obj, shape, updateValue);
}
static bool
@ -2045,8 +2032,13 @@ SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE);
}
Rooted<NativeObject*> nativeReceiver(cxArg, &receiver->as<NativeObject>());
return DefinePropertyOrElement<mode>(cxArg, nativeReceiver, id,
clasp->getProperty, clasp->setProperty,
JSPropertyOp getter = clasp->getProperty;
if (getter == JS_PropertyStub)
getter = nullptr;
JSStrictPropertyOp setter = clasp->setProperty;
if (setter == JS_StrictPropertyStub)
setter = nullptr;
return DefinePropertyOrElement<mode>(cxArg, nativeReceiver, id, getter, setter,
JSPROP_ENUMERATE, v, true, strict);
}

View File

@ -717,15 +717,19 @@ RegExpCompartment::createMatchResultTemplateObject(JSContext *cx)
/* Set dummy index property */
RootedValue index(cx, Int32Value(0));
if (!baseops::DefineProperty(cx, templateObject, cx->names().index, index,
JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE))
if (!baseops::DefineProperty(cx, templateObject, cx->names().index, index, nullptr, nullptr,
JSPROP_ENUMERATE))
{
return matchResultTemplateObject_; // = nullptr
}
/* Set dummy input property */
RootedValue inputVal(cx, StringValue(cx->runtime()->emptyString));
if (!baseops::DefineProperty(cx, templateObject, cx->names().input, inputVal,
JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE))
if (!baseops::DefineProperty(cx, templateObject, cx->names().input, inputVal, nullptr, nullptr,
JSPROP_ENUMERATE))
{
return matchResultTemplateObject_; // = nullptr
}
// Make sure that the properties are in the right slots.
DebugOnly<Shape *> shape = templateObject->lastProperty();