Commit e04d0b23 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Make integer indexed properties ("elements") work for proxies.

Rehome some Object/JSReceiver/JSObject methods.

R=ricow@chromium.org,kmillikin@chromium.org
BUG=v8:1543
TEST=

Review URL: http://codereview.chromium.org/7795055

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9381 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 35cb252a
......@@ -978,6 +978,12 @@ Handle<String> Factory::NumberToString(Handle<Object> number) {
}
Handle<String> Factory::Uint32ToString(uint32_t value) {
CALL_HEAP_FUNCTION(isolate(),
isolate()->heap()->Uint32ToString(value), String);
}
Handle<NumberDictionary> Factory::DictionaryAtNumberPut(
Handle<NumberDictionary> dictionary,
uint32_t key,
......
......@@ -351,6 +351,7 @@ class Factory {
PropertyAttributes attributes);
Handle<String> NumberToString(Handle<Object> number);
Handle<String> Uint32ToString(uint32_t value);
enum ApiInstanceType {
JavaScriptObject,
......
......@@ -2532,6 +2532,15 @@ MaybeObject* Heap::NumberToString(Object* number,
}
MaybeObject* Heap::Uint32ToString(uint32_t value,
bool check_number_string_cache) {
Object* number;
MaybeObject* maybe = NumberFromUint32(value);
if (!maybe->To<Object>(&number)) return maybe;
return NumberToString(number, check_number_string_cache);
}
Map* Heap::MapForExternalArrayType(ExternalArrayType array_type) {
return Map::cast(roots_[RootIndexForExternalArrayType(array_type)]);
}
......
......@@ -1291,6 +1291,8 @@ class Heap {
MUST_USE_RESULT MaybeObject* NumberToString(
Object* number, bool check_number_string_cache = true);
MUST_USE_RESULT MaybeObject* Uint32ToString(
uint32_t value, bool check_number_string_cache = true);
Map* MapForExternalArrayType(ExternalArrayType array_type);
RootListIndex RootIndexForExternalArrayType(
......
......@@ -4253,8 +4253,11 @@ bool JSObject::HasHiddenProperties() {
}
bool JSObject::HasElement(uint32_t index) {
return HasElementWithReceiver(this, index);
bool JSReceiver::HasElement(uint32_t index) {
if (IsJSProxy()) {
return JSProxy::cast(this)->HasElementWithHandler(index);
}
return JSObject::cast(this)->HasElementWithReceiver(this, index);
}
......
This diff is collapsed.
......@@ -923,10 +923,6 @@ class Object : public MaybeObject {
LookupResult* result,
String* key,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver,
Object* structure,
String* name,
Object* holder);
MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
JSFunction* getter);
......@@ -1352,6 +1348,14 @@ class JSReceiver: public HeapObject {
Object* value);
MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
// Set the index'th array element.
// Can cause GC, or return failure if GC is required.
MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
Object* value,
StrictModeFlag strict_mode,
bool check_prototype);
// Returns the class name ([[Class]] property in the specification).
String* class_name();
......@@ -1368,6 +1372,7 @@ class JSReceiver: public HeapObject {
// Can cause a GC.
inline bool HasProperty(String* name);
inline bool HasLocalProperty(String* name);
inline bool HasElement(uint32_t index);
// Return the object's prototype (might be Heap::null_value()).
inline Object* GetPrototype();
......@@ -1456,6 +1461,10 @@ class JSObject: public JSReceiver {
// a dictionary, and it will stay a dictionary.
MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit);
MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver,
Object* structure,
String* name);
// Can cause GC.
MUST_USE_RESULT MaybeObject* SetPropertyForResult(LookupResult* result,
String* key,
......@@ -1612,7 +1621,6 @@ class JSObject: public JSReceiver {
bool CanConvertToFastDoubleElements();
// Tells whether the index'th element is present.
inline bool HasElement(uint32_t index);
bool HasElementWithReceiver(JSReceiver* receiver, uint32_t index);
// Computes the new capacity when expanding the elements of a JSObject.
......@@ -6630,24 +6638,47 @@ class JSProxy: public JSReceiver {
static inline JSProxy* cast(Object* obj);
bool HasPropertyWithHandler(String* name);
bool HasElementWithHandler(uint32_t index);
MUST_USE_RESULT MaybeObject* GetPropertyWithHandler(
Object* receiver,
String* name);
MUST_USE_RESULT MaybeObject* GetElementWithHandler(
Object* receiver,
uint32_t index);
MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetElementWithHandler(
uint32_t index,
Object* value,
StrictModeFlag strict_mode);
// If the handler defines an accessor property, invoke its setter
// (or throw if only a getter exists) and set *found to true. Otherwise false.
MUST_USE_RESULT MaybeObject* SetPropertyWithHandlerIfDefiningSetter(
String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool* found);
MUST_USE_RESULT MaybeObject* DeletePropertyWithHandler(
String* name,
DeleteMode mode);
MUST_USE_RESULT MaybeObject* DeleteElementWithHandler(
uint32_t index,
DeleteMode mode);
MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
JSReceiver* receiver,
String* name);
MUST_USE_RESULT PropertyAttributes GetElementAttributeWithHandler(
JSReceiver* receiver,
uint32_t index);
// Turn this into an (empty) JSObject.
void Fix();
......
......@@ -4329,6 +4329,14 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
return isolate->Throw(*error);
}
if (object->IsJSProxy()) {
bool has_pending_exception = false;
Handle<Object> name = Execution::ToString(key, &has_pending_exception);
if (has_pending_exception) return Failure::Exception();
return JSProxy::cast(*object)->SetProperty(
String::cast(*name), *value, attr, strict_mode);
}
// If the object isn't a JavaScript object, we ignore the store.
if (!object->IsJSObject()) return *value;
......@@ -4448,7 +4456,7 @@ MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
// Check if the given key is an array index.
uint32_t index;
if (receiver->IsJSObject() && key->ToArrayIndex(&index)) {
if (key->ToArrayIndex(&index)) {
// In Firefox/SpiderMonkey, Safari and Opera you can access the
// characters of a string using [] notation. In the case of a
// String object we just need to redirect the deletion to the
......@@ -4459,8 +4467,7 @@ MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
return isolate->heap()->true_value();
}
return JSObject::cast(*receiver)->DeleteElement(
index, JSReceiver::FORCE_DELETION);
return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION);
}
Handle<String> key_string;
......@@ -4622,31 +4629,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
CONVERT_CHECKED(JSReceiver, receiver, args[0]);
CONVERT_CHECKED(String, key, args[1]);
// Only JS receivers can have properties.
if (args[0]->IsJSReceiver()) {
JSReceiver* receiver = JSReceiver::cast(args[0]);
CONVERT_CHECKED(String, key, args[1]);
bool result = receiver->HasProperty(key);
if (isolate->has_pending_exception()) return Failure::Exception();
return isolate->heap()->ToBoolean(result);
}
return isolate->heap()->false_value();
bool result = receiver->HasProperty(key);
if (isolate->has_pending_exception()) return Failure::Exception();
return isolate->heap()->ToBoolean(result);
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
CONVERT_CHECKED(JSReceiver, receiver, args[0]);
CONVERT_CHECKED(Smi, index, args[1]);
// Only JS objects can have elements.
if (args[0]->IsJSObject()) {
JSObject* object = JSObject::cast(args[0]);
CONVERT_CHECKED(Smi, index_obj, args[1]);
uint32_t index = index_obj->value();
if (object->HasElement(index)) return isolate->heap()->true_value();
}
return isolate->heap()->false_value();
bool result = receiver->HasElement(index->value());
if (isolate->has_pending_exception()) return Failure::Exception();
return isolate->heap()->ToBoolean(result);
}
......@@ -10079,8 +10079,8 @@ static MaybeObject* DebugLookupResultValue(Heap* heap,
case CALLBACKS: {
Object* structure = result->GetCallbackObject();
if (structure->IsForeign() || structure->IsAccessorInfo()) {
MaybeObject* maybe_value = receiver->GetPropertyWithCallback(
receiver, structure, name, result->holder());
MaybeObject* maybe_value = result->holder()->GetPropertyWithCallback(
receiver, structure, name);
if (!maybe_value->ToObject(&value)) {
if (maybe_value->IsRetryAfterGC()) return maybe_value;
ASSERT(maybe_value->IsException());
......
......@@ -355,7 +355,7 @@ function IN(x) {
if (!IS_SPEC_OBJECT(x)) {
throw %MakeTypeError('invalid_in_operator_use', [this, x]);
}
return %_IsNonNegativeSmi(this) && !%IsJSProxy(x) ?
return %_IsNonNegativeSmi(this) ?
%HasElement(x, this) : %HasProperty(x, %ToString(this));
}
......
......@@ -1043,7 +1043,7 @@ function ProxyFix(obj) {
throw MakeTypeError("handler_returned_undefined", [handler, "fix"]);
}
if (IS_SPEC_FUNCTION(obj)) {
if (%IsJSFunctionProxy(obj)) {
var callTrap = %GetCallTrap(obj);
var constructTrap = %GetConstructTrap(obj);
var code = DelegateCallAndConstruct(callTrap, constructTrap);
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment