mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-04 23:08:39 +09:00
Mix 55 js engine backporting mostly bugfixes.
1369337 - Forcibly create length and @@iterator properties for arguments when redefining. 1369680 - Use HasOwnProperty when resolving lazy properties to avoid triggering proxy traps in the proto-chain. 1319443 - Fix GlobalScopes XDR to encode global function bindings. 1335571 - Use template craziness to allow covering more cases with compartment asserts.
This commit is contained in:
parent
f4b5f122a6
commit
d116bfdfef
7 changed files with 107 additions and 25 deletions
|
|
@ -2611,7 +2611,7 @@ JS_ForwardSetPropertyTo(JSContext* cx, HandleObject obj, HandleId id, HandleValu
|
|||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, id, receiver);
|
||||
assertSameCompartment(cx, obj, id, v, receiver);
|
||||
|
||||
return SetProperty(cx, obj, id, v, receiver, result);
|
||||
}
|
||||
|
|
@ -2621,7 +2621,7 @@ JS_SetPropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
|
|||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, id);
|
||||
assertSameCompartment(cx, obj, id, v);
|
||||
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
ObjectOpResult ignored;
|
||||
|
|
@ -2775,7 +2775,7 @@ JS_Enumerate(JSContext* cx, HandleObject obj, JS::MutableHandle<IdVector> props)
|
|||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
assertSameCompartment(cx, obj, props);
|
||||
MOZ_ASSERT(props.empty());
|
||||
|
||||
AutoIdVector ids(cx);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,25 @@ class CompartmentChecker
|
|||
check(handle.get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void check(MutableHandle<T> handle) {
|
||||
check(handle.get());
|
||||
}
|
||||
template <typename T>
|
||||
void checkAtom(T* thing) {
|
||||
static_assert(mozilla::IsSame<T, JSAtom>::value ||
|
||||
mozilla::IsSame<T, JS::Symbol>::value,
|
||||
"Should only be called with JSAtom* or JS::Symbol* argument");
|
||||
#ifdef DEBUG
|
||||
// Atoms which move across zone boundaries need to be marked in the new
|
||||
// zone, see JS_MarkCrossZoneId.
|
||||
if (compartment) {
|
||||
JSRuntime* rt = compartment->runtimeFromAnyThread();
|
||||
MOZ_ASSERT(rt->gc.atomMarking.atomIsMarked(compartment->zone(), thing));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void check(JSString* str) {
|
||||
MOZ_ASSERT(!js::gc::detail::CellIsMarkedGray(str));
|
||||
if (!str->isAtom())
|
||||
|
|
@ -95,6 +114,20 @@ class CompartmentChecker
|
|||
check(v.toString());
|
||||
}
|
||||
|
||||
// Check the contents of any container class that supports the C++
|
||||
// iteration protocol, eg GCVector<jsid>.
|
||||
template <typename Container>
|
||||
typename mozilla::EnableIf<
|
||||
mozilla::IsSame<
|
||||
decltype(((Container*)nullptr)->begin()),
|
||||
decltype(((Container*)nullptr)->end())
|
||||
>::value
|
||||
>::Type
|
||||
check(const Container& container) {
|
||||
for (auto i : container)
|
||||
check(i);
|
||||
}
|
||||
|
||||
void check(const ValueArray& arr) {
|
||||
for (size_t i = 0; i < arr.length; i++)
|
||||
check(arr.array[i]);
|
||||
|
|
|
|||
|
|
@ -82,16 +82,16 @@ fun_enumerate(JSContext* cx, HandleObject obj)
|
|||
|
||||
if (!obj->isBoundFunction() && !obj->as<JSFunction>().isArrow()) {
|
||||
id = NameToId(cx->names().prototype);
|
||||
if (!HasProperty(cx, obj, id, &found))
|
||||
if (!HasOwnProperty(cx, obj, id, &found))
|
||||
return false;
|
||||
}
|
||||
|
||||
id = NameToId(cx->names().length);
|
||||
if (!HasProperty(cx, obj, id, &found))
|
||||
if (!HasOwnProperty(cx, obj, id, &found))
|
||||
return false;
|
||||
|
||||
id = NameToId(cx->names().name);
|
||||
if (!HasProperty(cx, obj, id, &found))
|
||||
if (!HasOwnProperty(cx, obj, id, &found))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -514,6 +514,34 @@ DefineArgumentsIterator(JSContext* cx, Handle<ArgumentsObject*> argsobj)
|
|||
return NativeDefineProperty(cx, argsobj, iteratorId, val, nullptr, nullptr, JSPROP_RESOLVING);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ArgumentsObject::reifyLength(JSContext* cx, Handle<ArgumentsObject*> obj)
|
||||
{
|
||||
if (obj->hasOverriddenLength())
|
||||
return true;
|
||||
|
||||
RootedId id(cx, NameToId(cx->names().length));
|
||||
RootedValue val(cx, Int32Value(obj->initialLength()));
|
||||
if (!NativeDefineProperty(cx, obj, id, val, nullptr, nullptr, JSPROP_RESOLVING))
|
||||
return false;
|
||||
|
||||
obj->markLengthOverridden();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ArgumentsObject::reifyIterator(JSContext* cx, Handle<ArgumentsObject*> obj)
|
||||
{
|
||||
if (obj->hasOverriddenIterator())
|
||||
return true;
|
||||
|
||||
if (!DefineArgumentsIterator(cx, obj))
|
||||
return false;
|
||||
|
||||
obj->markIteratorOverridden();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
MappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
|
||||
{
|
||||
|
|
@ -567,20 +595,20 @@ MappedArgumentsObject::obj_enumerate(JSContext* cx, HandleObject obj)
|
|||
|
||||
// Trigger reflection.
|
||||
id = NameToId(cx->names().length);
|
||||
if (!HasProperty(cx, argsobj, id, &found))
|
||||
if (!HasOwnProperty(cx, argsobj, id, &found))
|
||||
return false;
|
||||
|
||||
id = NameToId(cx->names().callee);
|
||||
if (!HasProperty(cx, argsobj, id, &found))
|
||||
if (!HasOwnProperty(cx, argsobj, id, &found))
|
||||
return false;
|
||||
|
||||
id = SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator);
|
||||
if (!HasProperty(cx, argsobj, id, &found))
|
||||
if (!HasOwnProperty(cx, argsobj, id, &found))
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < argsobj->initialLength(); i++) {
|
||||
id = INT_TO_JSID(i);
|
||||
if (!HasProperty(cx, argsobj, id, &found))
|
||||
if (!HasOwnProperty(cx, argsobj, id, &found))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -757,20 +785,20 @@ UnmappedArgumentsObject::obj_enumerate(JSContext* cx, HandleObject obj)
|
|||
|
||||
// Trigger reflection.
|
||||
id = NameToId(cx->names().length);
|
||||
if (!HasProperty(cx, argsobj, id, &found))
|
||||
if (!HasOwnProperty(cx, argsobj, id, &found))
|
||||
return false;
|
||||
|
||||
id = NameToId(cx->names().callee);
|
||||
if (!HasProperty(cx, argsobj, id, &found))
|
||||
if (!HasOwnProperty(cx, argsobj, id, &found))
|
||||
return false;
|
||||
|
||||
id = SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator);
|
||||
if (!HasProperty(cx, argsobj, id, &found))
|
||||
if (!HasOwnProperty(cx, argsobj, id, &found))
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < argsobj->initialLength(); i++) {
|
||||
id = INT_TO_JSID(i);
|
||||
if (!HasProperty(cx, argsobj, id, &found))
|
||||
if (!HasOwnProperty(cx, argsobj, id, &found))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -232,6 +232,11 @@ class ArgumentsObject : public NativeObject
|
|||
setFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the default "length" property and set LENGTH_OVERRIDDEN_BIT.
|
||||
*/
|
||||
static bool reifyLength(JSContext* cx, Handle<ArgumentsObject*> obj);
|
||||
|
||||
/* True iff arguments[@@iterator] has been assigned or its attributes
|
||||
* changed. */
|
||||
bool hasOverriddenIterator() const {
|
||||
|
|
@ -243,6 +248,11 @@ class ArgumentsObject : public NativeObject
|
|||
uint32_t v = getFixedSlot(INITIAL_LENGTH_SLOT).toInt32() | ITERATOR_OVERRIDDEN_BIT;
|
||||
setFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the default @@iterator property and set ITERATOR_OVERRIDDEN_BIT.
|
||||
*/
|
||||
static bool reifyIterator(JSContext* cx, Handle<ArgumentsObject*> obj);
|
||||
|
||||
/* True iff any element has been assigned or its attributes
|
||||
* changed. */
|
||||
|
|
|
|||
|
|
@ -1453,21 +1453,26 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
return DefineTypedArrayElement(cx->asJSContext(), obj, index, desc_, result);
|
||||
}
|
||||
} else if (obj->is<ArgumentsObject>()) {
|
||||
Rooted<ArgumentsObject*> argsobj(cx, &obj->as<ArgumentsObject>());
|
||||
if (id == NameToId(cx->names().length)) {
|
||||
// Either we are resolving the .length property on this object, or
|
||||
// redefining it. In the latter case only, we must set a bit. To
|
||||
// distinguish the two cases, we note that when resolving, the
|
||||
// property won't already exist; whereas the first time it is
|
||||
// redefined, it will.
|
||||
if ((desc_.attributes() & JSPROP_RESOLVING) == 0)
|
||||
obj->as<ArgumentsObject>().markLengthOverridden();
|
||||
// Either we are resolving the .length property on this object,
|
||||
// or redefining it. In the latter case only, we must reify the
|
||||
// property. To distinguish the two cases, we note that when
|
||||
// resolving, the JSPROP_RESOLVING mask is set; whereas the first
|
||||
// time it is redefined, it isn't set.
|
||||
if ((desc_.attributes() & JSPROP_RESOLVING) == 0) {
|
||||
if (!ArgumentsObject::reifyLength(cx, argsobj))
|
||||
return false;
|
||||
}
|
||||
} else if (JSID_IS_SYMBOL(id) && JSID_TO_SYMBOL(id) == cx->wellKnownSymbols().iterator) {
|
||||
// Do same thing as .length for [@@iterator].
|
||||
if ((desc_.attributes() & JSPROP_RESOLVING) == 0)
|
||||
obj->as<ArgumentsObject>().markIteratorOverridden();
|
||||
if ((desc_.attributes() & JSPROP_RESOLVING) == 0) {
|
||||
if (!ArgumentsObject::reifyIterator(cx, argsobj))
|
||||
return false;
|
||||
}
|
||||
} else if (JSID_IS_INT(id)) {
|
||||
if ((desc_.attributes() & JSPROP_RESOLVING) == 0)
|
||||
obj->as<ArgumentsObject>().markElementOverridden();
|
||||
argsobj->markElementOverridden();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -972,6 +972,8 @@ GlobalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, MutableHandleScope scope)
|
|||
if (mode == XDR_DECODE)
|
||||
uniqueData.emplace(cx, data);
|
||||
|
||||
if (!xdr->codeUint32(&data->varStart))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&data->letStart))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&data->constStart))
|
||||
|
|
@ -979,6 +981,7 @@ GlobalScope::XDR(XDRState<mode>* xdr, ScopeKind kind, MutableHandleScope scope)
|
|||
|
||||
if (mode == XDR_DECODE) {
|
||||
if (!data->length) {
|
||||
MOZ_ASSERT(!data->varStart);
|
||||
MOZ_ASSERT(!data->letStart);
|
||||
MOZ_ASSERT(!data->constStart);
|
||||
}
|
||||
|
|
@ -1389,7 +1392,10 @@ js::DumpBindings(JSContext* cx, Scope* scopeArg)
|
|||
fprintf(stderr, "%s %s ", BindingKindString(bi.kind()), bytes.ptr());
|
||||
switch (bi.location().kind()) {
|
||||
case BindingLocation::Kind::Global:
|
||||
fprintf(stderr, "global\n");
|
||||
if (bi.isTopLevelFunction())
|
||||
fprintf(stderr, "global function\n");
|
||||
else
|
||||
fprintf(stderr, "global\n");
|
||||
break;
|
||||
case BindingLocation::Kind::Argument:
|
||||
fprintf(stderr, "arg slot %u\n", bi.location().argumentSlot());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue