Bug 904723, part 2 - Changes to _DefineDataProperty semantics. r=till.

Rename the _DefineValueProperty intrinsic to _DefineDataProperty and change
it to call js::DefineProperty rather than JSObject::defineProperty. The
difference is that the former is ES5-compliant in terms of interactions with
already-existing properties and the latter is not.  The new behavior is safe
to expose via Array.from as a capability anyone can use to define any element
on any object (it's just what Object.defineProperty already does).
This commit is contained in:
Jason Orendorff 2014-06-06 11:15:21 -04:00
parent 56cb95f6ad
commit 3a9fd0f200
3 changed files with 22 additions and 24 deletions

View File

@ -816,11 +816,11 @@ function SupportedLocales(availableLocales, requestedLocales, options) {
// Step 4.
for (var i = 0; i < subset.length; i++) {
_DefineValueProperty(subset, i, subset[i],
ATTR_ENUMERABLE | ATTR_NONCONFIGURABLE | ATTR_NONWRITABLE);
_DefineDataProperty(subset, i, subset[i],
ATTR_ENUMERABLE | ATTR_NONCONFIGURABLE | ATTR_NONWRITABLE);
}
_DefineValueProperty(subset, "length", subset.length,
ATTR_NONENUMERABLE | ATTR_NONCONFIGURABLE | ATTR_NONWRITABLE);
_DefineDataProperty(subset, "length", subset.length,
ATTR_NONENUMERABLE | ATTR_NONCONFIGURABLE | ATTR_NONWRITABLE);
// Step 5.
return subset;
@ -896,7 +896,7 @@ function GetNumberOption(options, property, minimum, maximum, fallback) {
* to avoid interference from setters on Object.prototype.
*/
function defineProperty(o, p, v) {
_DefineValueProperty(o, p, v, ATTR_ENUMERABLE | ATTR_CONFIGURABLE | ATTR_WRITABLE);
_DefineDataProperty(o, p, v, ATTR_ENUMERABLE | ATTR_CONFIGURABLE | ATTR_WRITABLE);
}

View File

@ -1016,7 +1016,7 @@ bool intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp);
bool intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp);
bool intrinsic_UnsafePutElements(JSContext *cx, unsigned argc, Value *vp);
bool intrinsic_DefineValueProperty(JSContext *cx, unsigned argc, Value *vp);
bool intrinsic_DefineDataProperty(JSContext *cx, unsigned argc, Value *vp);
bool intrinsic_UnsafeSetReservedSlot(JSContext *cx, unsigned argc, Value *vp);
bool intrinsic_UnsafeGetReservedSlot(JSContext *cx, unsigned argc, Value *vp);
bool intrinsic_HaveSameClass(JSContext *cx, unsigned argc, Value *vp);

View File

@ -460,7 +460,7 @@ js::intrinsic_UnsafePutElements(JSContext *cx, unsigned argc, Value *vp)
}
bool
js::intrinsic_DefineValueProperty(JSContext *cx, unsigned argc, Value *vp)
js::intrinsic_DefineDataProperty(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
@ -469,36 +469,34 @@ js::intrinsic_DefineValueProperty(JSContext *cx, unsigned argc, Value *vp)
MOZ_ASSERT(args[3].isInt32());
RootedObject obj(cx, &args[0].toObject());
if (obj->is<ProxyObject>()) {
JS_ReportError(cx, "_DefineValueProperty can't be used on proxies");
return false;
}
RootedId id(cx);
if (!ValueToId<CanGC>(cx, args[1], &id))
return false;
RootedValue value(cx, args[2]);
unsigned attributes = args[3].toInt32();
unsigned resolvedAttributes = JSPROP_PERMANENT | JSPROP_READONLY;
Rooted<PropDesc> desc(cx);
MOZ_ASSERT(bool(attributes & ATTR_ENUMERABLE) != bool(attributes & ATTR_NONENUMERABLE),
"_DefineValueProperty must receive either ATTR_ENUMERABLE xor ATTR_NONENUMERABLE");
if (attributes & ATTR_ENUMERABLE)
resolvedAttributes |= JSPROP_ENUMERATE;
"_DefineDataProperty must receive either ATTR_ENUMERABLE xor ATTR_NONENUMERABLE");
PropDesc::Enumerability enumerable =
PropDesc::Enumerability(bool(attributes & ATTR_ENUMERABLE));
MOZ_ASSERT(bool(attributes & ATTR_CONFIGURABLE) != bool(attributes & ATTR_NONCONFIGURABLE),
"_DefineValueProperty must receive either ATTR_CONFIGURABLE xor "
"_DefineDataProperty must receive either ATTR_CONFIGURABLE xor "
"ATTR_NONCONFIGURABLE");
if (attributes & ATTR_CONFIGURABLE)
resolvedAttributes &= ~JSPROP_PERMANENT;
PropDesc::Configurability configurable =
PropDesc::Configurability(bool(attributes & ATTR_CONFIGURABLE));
MOZ_ASSERT(bool(attributes & ATTR_WRITABLE) != bool(attributes & ATTR_NONWRITABLE),
"_DefineValueProperty must receive either ATTR_WRITABLE xor ATTR_NONWRITABLE");
if (attributes & ATTR_WRITABLE)
resolvedAttributes &= ~JSPROP_READONLY;
"_DefineDataProperty must receive either ATTR_WRITABLE xor ATTR_NONWRITABLE");
PropDesc::Writability writable =
PropDesc::Writability(bool(attributes & ATTR_WRITABLE));
return JSObject::defineGeneric(cx, obj, id, value, JS_PropertyStub, JS_StrictPropertyStub,
resolvedAttributes);
desc.set(PropDesc(value, writable, enumerable, configurable));
bool result;
return DefineProperty(cx, obj, id, desc, true, &result);
}
bool
@ -772,7 +770,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0),
JS_FN("UnsafePutElements", intrinsic_UnsafePutElements, 3,0),
JS_FN("_DefineValueProperty", intrinsic_DefineValueProperty, 4,0),
JS_FN("_DefineDataProperty", intrinsic_DefineDataProperty, 4,0),
JS_FN("UnsafeSetReservedSlot", intrinsic_UnsafeSetReservedSlot, 3,0),
JS_FN("UnsafeGetReservedSlot", intrinsic_UnsafeGetReservedSlot, 2,0),
JS_FN("HaveSameClass", intrinsic_HaveSameClass, 2,0),