mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 739380 - Start to implement the default [[GetP]] hook from the proto-climbing refactoring for the various element types. r=bhackett
--HG-- extra : rebase_source : 0270610c88d3315023a4cc582abbaf62dcf8a1cc
This commit is contained in:
parent
3518781dd9
commit
e07abf10ae
@ -703,6 +703,14 @@ MagicValue(JSWhyMagic why)
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NumberValue(float f)
|
||||
{
|
||||
Value v;
|
||||
v.setNumber(f);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NumberValue(double dbl)
|
||||
{
|
||||
@ -711,6 +719,55 @@ NumberValue(double dbl)
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NumberValue(size_t s)
|
||||
{
|
||||
Value v;
|
||||
if (s > JSVAL_INT_MAX)
|
||||
v.setDouble(s);
|
||||
else
|
||||
v.setInt32(int32_t(s));
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NumberValue(int8_t i)
|
||||
{
|
||||
return Int32Value(i);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NumberValue(uint8_t i)
|
||||
{
|
||||
return Int32Value(i);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NumberValue(int16_t i)
|
||||
{
|
||||
return Int32Value(i);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NumberValue(uint16_t i)
|
||||
{
|
||||
return Int32Value(i);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NumberValue(int32_t i)
|
||||
{
|
||||
return Int32Value(i);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
NumberValue(uint32_t i)
|
||||
{
|
||||
Value v;
|
||||
v.setNumber(i);
|
||||
return v;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
ObjectOrNullValue(JSObject *obj)
|
||||
{
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "jsscope.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "js/TemplateLib.h"
|
||||
|
||||
#include "Debugger.h"
|
||||
#include "ObjectImpl.h"
|
||||
|
||||
@ -288,6 +290,63 @@ js::ObjectImpl::markChildren(JSTracer *trc)
|
||||
MarkObjectSlots(trc, obj, 0, obj->slotSpan());
|
||||
}
|
||||
|
||||
bool
|
||||
DenseElementsHeader::getOwnElement(JSContext *cx, ObjectImpl *obj, uint32_t index, PropDesc *desc)
|
||||
{
|
||||
MOZ_ASSERT(this == &obj->elementsHeader());
|
||||
|
||||
uint32_t len = initializedLength();
|
||||
if (index >= len) {
|
||||
*desc = PropDesc::undefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
HeapSlot &slot = obj->elements[index];
|
||||
if (slot.isMagic(JS_ARRAY_HOLE)) {
|
||||
*desc = PropDesc::undefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
*desc = PropDesc(slot, PropDesc::Writable, PropDesc::Enumerable, PropDesc::Configurable);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SparseElementsHeader::getOwnElement(JSContext *cx, ObjectImpl *obj, uint32_t index, PropDesc *desc)
|
||||
{
|
||||
MOZ_ASSERT(this == &obj->elementsHeader());
|
||||
|
||||
MOZ_NOT_REACHED("NYI");
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool
|
||||
TypedElementsHeader<T>::getOwnElement(JSContext *cx, ObjectImpl *obj, uint32_t index,
|
||||
PropDesc *desc)
|
||||
{
|
||||
MOZ_ASSERT(this == &obj->elementsHeader());
|
||||
|
||||
if (index >= length()) {
|
||||
*desc = PropDesc::undefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
*desc = PropDesc(NumberValue(getElement(index)), PropDesc::Writable,
|
||||
PropDesc::Enumerable, PropDesc::Configurable);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferElementsHeader::getOwnElement(JSContext *cx, ObjectImpl *obj, uint32_t index,
|
||||
PropDesc *desc)
|
||||
{
|
||||
MOZ_ASSERT(this == &obj->elementsHeader());
|
||||
|
||||
MOZ_NOT_REACHED("NYI");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
SparseElementsHeader::defineElement(JSContext *cx, ObjectImpl *obj, uint32_t index,
|
||||
const PropDesc &desc, bool shouldThrow, bool *succeeded)
|
||||
@ -345,7 +404,7 @@ DenseElementsHeader::defineElement(JSContext *cx, ObjectImpl *obj, uint32_t inde
|
||||
return true;
|
||||
MOZ_ALWAYS_FALSE(js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_OBJECT_NOT_EXTENSIBLE,
|
||||
JSDVG_IGNORE_STACK,
|
||||
ObjectValue(*obj->asObjectPtr()),
|
||||
ObjectValue(*obj),
|
||||
NULL, NULL, NULL));
|
||||
return false;
|
||||
}
|
||||
@ -393,7 +452,7 @@ TypedElementsHeader<T>::defineElement(JSContext *cx, ObjectImpl *obj,
|
||||
*succeeded = false;
|
||||
js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_OBJECT_NOT_EXTENSIBLE,
|
||||
JSDVG_IGNORE_STACK,
|
||||
ObjectValue(*(JSObject*)obj), // XXX jwalden dodgy cast
|
||||
ObjectValue(*obj),
|
||||
NULL, NULL, NULL);
|
||||
return false;
|
||||
}
|
||||
@ -411,6 +470,108 @@ ArrayBufferElementsHeader::defineElement(JSContext *cx, ObjectImpl *obj,
|
||||
return DefineElement(cx, delegate, index, desc, shouldThrow, succeeded);
|
||||
}
|
||||
|
||||
bool
|
||||
js::GetElement(JSContext *cx, ObjectImpl *obj, ObjectImpl *receiver, uint32_t index,
|
||||
Value *vp)
|
||||
{
|
||||
NEW_OBJECT_REPRESENTATION_ONLY();
|
||||
|
||||
do {
|
||||
MOZ_ASSERT(obj);
|
||||
|
||||
if (static_cast<JSObject *>(obj)->isProxy()) { // XXX
|
||||
MOZ_NOT_REACHED("NYI: proxy [[GetP]]");
|
||||
return false;
|
||||
}
|
||||
|
||||
ElementsHeader &header = obj->elementsHeader();
|
||||
|
||||
bool res;
|
||||
PropDesc desc;
|
||||
switch (header.kind()) {
|
||||
case DenseElements:
|
||||
res = header.asDenseElements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case SparseElements:
|
||||
res = header.asSparseElements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case Uint8Elements:
|
||||
res = header.asUint8Elements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case Int8Elements:
|
||||
res = header.asInt8Elements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case Uint16Elements:
|
||||
res = header.asUint16Elements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case Int16Elements:
|
||||
res = header.asInt16Elements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case Uint32Elements:
|
||||
res = header.asUint32Elements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case Int32Elements:
|
||||
res = header.asInt32Elements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case Uint8ClampedElements:
|
||||
res = header.asUint8ClampedElements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case Float32Elements:
|
||||
res = header.asFloat32Elements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case Float64Elements:
|
||||
res = header.asFloat64Elements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
case ArrayBufferElements:
|
||||
res = header.asArrayBufferElements().getOwnElement(cx, obj, index, &desc);
|
||||
break;
|
||||
}
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
/* No property? Recur or bottom out. */
|
||||
if (desc.isUndefined()) {
|
||||
obj = obj->getProto();
|
||||
if (obj)
|
||||
continue;
|
||||
|
||||
vp->setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If it's a data property, return the value. */
|
||||
if (desc.isDataDescriptor()) {
|
||||
*vp = desc.value();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If it's an accessor property, call its [[Get]] with the receiver. */
|
||||
if (desc.isAccessorDescriptor()) {
|
||||
Value get = desc.getterValue();
|
||||
if (get.isUndefined()) {
|
||||
vp->setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
InvokeArgsGuard args;
|
||||
if (!cx->stack.pushInvokeArgs(cx, 0, &args))
|
||||
return false;
|
||||
|
||||
/* Push fval, thisv, and the args. */
|
||||
args.calleev() = get;
|
||||
args.thisv() = ObjectValue(*receiver);
|
||||
|
||||
bool ok = Invoke(cx, args);
|
||||
*vp = args.rval();
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Otherwise it's a PropertyOp-based property. XXX handle this! */
|
||||
MOZ_NOT_REACHED("NYI: handle PropertyOp'd properties here");
|
||||
return false;
|
||||
} while (false);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineElement(JSContext *cx, ObjectImpl *obj, uint32_t index, const PropDesc &desc,
|
||||
bool shouldThrow, bool *succeeded)
|
||||
|
@ -68,8 +68,27 @@ struct PropDesc {
|
||||
friend class AutoPropDescArrayRooter;
|
||||
friend void JS::AutoGCRooter::trace(JSTracer *trc);
|
||||
|
||||
enum Enumerability { Enumerable = true, NonEnumerable = false };
|
||||
enum Configurability { Configurable = true, NonConfigurable = false };
|
||||
enum Writability { Writable = true, NonWritable = false };
|
||||
|
||||
PropDesc();
|
||||
|
||||
static PropDesc undefined() { return PropDesc(); }
|
||||
|
||||
PropDesc(const Value &v, Writability writable,
|
||||
Enumerability enumerable, Configurability configurable)
|
||||
: pd_(UndefinedValue()),
|
||||
value_(v),
|
||||
get_(UndefinedValue()), set_(UndefinedValue()),
|
||||
attrs((writable ? 0 : JSPROP_READONLY) |
|
||||
(enumerable ? JSPROP_ENUMERATE : 0) |
|
||||
(configurable ? 0 : JSPROP_PERMANENT)),
|
||||
hasGet_(false), hasSet_(false),
|
||||
hasValue_(true), hasWritable_(true), hasEnumerable_(true), hasConfigurable_(true),
|
||||
isUndefined_(false)
|
||||
{}
|
||||
|
||||
/*
|
||||
* 8.10.5 ToPropertyDescriptor(Obj)
|
||||
*
|
||||
@ -94,8 +113,6 @@ struct PropDesc {
|
||||
void initFromPropertyDescriptor(const PropertyDescriptor &desc);
|
||||
bool makeObject(JSContext *cx);
|
||||
|
||||
void setUndefined() { isUndefined_ = true; }
|
||||
|
||||
bool isUndefined() const { return isUndefined_; }
|
||||
|
||||
bool hasGet() const { MOZ_ASSERT(!isUndefined()); return hasGet_; }
|
||||
@ -304,6 +321,8 @@ class DenseElementsHeader : public ElementsHeader
|
||||
return ElementsHeader::length;
|
||||
}
|
||||
|
||||
bool getOwnElement(JSContext *cx, ObjectImpl *obj, uint32_t index, PropDesc *desc);
|
||||
|
||||
bool defineElement(JSContext *cx, ObjectImpl *obj, uint32_t index, const PropDesc &desc,
|
||||
bool shouldThrow, bool *succeeded);
|
||||
|
||||
@ -328,6 +347,8 @@ class SparseElementsHeader : public ElementsHeader
|
||||
return ElementsHeader::length;
|
||||
}
|
||||
|
||||
bool getOwnElement(JSContext *cx, ObjectImpl *obj, uint32_t index, PropDesc *desc);
|
||||
|
||||
bool defineElement(JSContext *cx, ObjectImpl *obj, uint32_t index, const PropDesc &desc,
|
||||
bool shouldThrow, bool *succeeded);
|
||||
|
||||
@ -431,11 +452,20 @@ template<> inline const bool TypeIsUint8Clamped<uint8_clamped>() { return true;
|
||||
template <typename T>
|
||||
class TypedElementsHeader : public ElementsHeader
|
||||
{
|
||||
T getElement(uint32_t index) {
|
||||
MOZ_ASSERT(index < length());
|
||||
return reinterpret_cast<T *>(this + 1)[index];
|
||||
}
|
||||
|
||||
public:
|
||||
uint32_t byteLength() const {
|
||||
uint32_t length() const {
|
||||
MOZ_ASSERT(Uint8Elements <= kind());
|
||||
MOZ_ASSERT(kind() <= Float64Elements);
|
||||
return ElementsHeader::length;
|
||||
}
|
||||
|
||||
bool getOwnElement(JSContext *cx, ObjectImpl *obj, uint32_t index, PropDesc *desc);
|
||||
|
||||
bool defineElement(JSContext *cx, ObjectImpl *obj, uint32_t index, const PropDesc &desc,
|
||||
bool shouldThrow, bool *succeeded);
|
||||
|
||||
@ -521,6 +551,8 @@ class Uint8ClampedElementsHeader : public TypedElementsHeader<uint8_clamped>
|
||||
class ArrayBufferElementsHeader : public ElementsHeader
|
||||
{
|
||||
public:
|
||||
bool getOwnElement(JSContext *cx, ObjectImpl *obj, uint32_t index, PropDesc *desc);
|
||||
|
||||
bool defineElement(JSContext *cx, ObjectImpl *obj, uint32_t index, const PropDesc &desc,
|
||||
bool shouldThrow, bool *succeeded);
|
||||
|
||||
@ -686,6 +718,9 @@ struct Shape;
|
||||
|
||||
class NewObjectCache;
|
||||
|
||||
inline Value
|
||||
ObjectValue(ObjectImpl &obj);
|
||||
|
||||
/*
|
||||
* ObjectImpl specifies the internal implementation of an object. (In contrast
|
||||
* JSObject specifies an "external" interface, at the conceptual level of that
|
||||
@ -772,6 +807,8 @@ class ObjectImpl : public gc::Cell
|
||||
|
||||
JSObject * asObjectPtr() { return reinterpret_cast<JSObject *>(this); }
|
||||
|
||||
friend inline Value ObjectValue(ObjectImpl &obj);
|
||||
|
||||
/* These functions are public, and they should remain public. */
|
||||
|
||||
public:
|
||||
@ -1082,6 +1119,18 @@ class ObjectImpl : public gc::Cell
|
||||
static size_t offsetOfSlots() { return offsetof(ObjectImpl, slots); }
|
||||
};
|
||||
|
||||
inline Value
|
||||
ObjectValue(ObjectImpl &obj)
|
||||
{
|
||||
Value v;
|
||||
v.setObject(*obj.asObjectPtr());
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Proposed default [[GetP]](Receiver, P) method. */
|
||||
extern bool
|
||||
GetElement(JSContext *cx, ObjectImpl *obj, ObjectImpl *receiver, uint32_t index, Value *vp);
|
||||
|
||||
extern bool
|
||||
DefineElement(JSContext *cx, ObjectImpl *obj, uint32_t index, const PropDesc &desc,
|
||||
bool shouldThrow, bool *succeeded);
|
||||
|
Loading…
Reference in New Issue
Block a user