summaryrefslogtreecommitdiff
path: root/src/3rdparty/v8/src/accessors.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/v8/src/accessors.cc')
-rw-r--r--src/3rdparty/v8/src/accessors.cc195
1 files changed, 146 insertions, 49 deletions
diff --git a/src/3rdparty/v8/src/accessors.cc b/src/3rdparty/v8/src/accessors.cc
index 8048738..c2f245c 100644
--- a/src/3rdparty/v8/src/accessors.cc
+++ b/src/3rdparty/v8/src/accessors.cc
@@ -42,15 +42,11 @@ namespace internal {
template <class C>
-static C* FindInPrototypeChain(Object* obj, bool* found_it) {
- ASSERT(!*found_it);
- Heap* heap = HEAP;
- while (!Is<C>(obj)) {
- if (obj == heap->null_value()) return NULL;
- obj = obj->GetPrototype();
+static C* FindInstanceOf(Object* obj) {
+ for (Object* cur = obj; !cur->IsNull(); cur = cur->GetPrototype()) {
+ if (Is<C>(cur)) return C::cast(cur);
}
- *found_it = true;
- return C::cast(obj);
+ return NULL;
}
@@ -81,10 +77,8 @@ MaybeObject* Accessors::ReadOnlySetAccessor(JSObject*, Object* value, void*) {
MaybeObject* Accessors::ArrayGetLength(Object* object, void*) {
// Traverse the prototype chain until we reach an array.
- bool found_it = false;
- JSArray* holder = FindInPrototypeChain<JSArray>(object, &found_it);
- if (!found_it) return Smi::FromInt(0);
- return holder->length();
+ JSArray* holder = FindInstanceOf<JSArray>(object);
+ return holder == NULL ? Smi::FromInt(0) : holder->length();
}
@@ -92,15 +86,56 @@ MaybeObject* Accessors::ArrayGetLength(Object* object, void*) {
Object* Accessors::FlattenNumber(Object* value) {
if (value->IsNumber() || !value->IsJSValue()) return value;
JSValue* wrapper = JSValue::cast(value);
- ASSERT(Isolate::Current()->context()->global_context()->number_function()->
+ ASSERT(Isolate::Current()->context()->native_context()->number_function()->
has_initial_map());
- Map* number_map = Isolate::Current()->context()->global_context()->
+ Map* number_map = Isolate::Current()->context()->native_context()->
number_function()->initial_map();
if (wrapper->map() == number_map) return wrapper->value();
return value;
}
+static MaybeObject* ArraySetLengthObserved(Isolate* isolate,
+ Handle<JSArray> array,
+ Handle<Object> new_length_handle) {
+ List<Handle<String> > indices;
+ List<Handle<Object> > old_values;
+ Handle<Object> old_length_handle(array->length(), isolate);
+ uint32_t old_length = 0;
+ CHECK(old_length_handle->ToArrayIndex(&old_length));
+ uint32_t new_length = 0;
+ CHECK(new_length_handle->ToArrayIndex(&new_length));
+ // TODO(adamk): This loop can be very slow for arrays in dictionary mode.
+ // Find another way to iterate over arrays with dictionary elements.
+ for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
+ PropertyAttributes attributes = array->GetLocalElementAttribute(i);
+ if (attributes == ABSENT) continue;
+ // A non-configurable property will cause the truncation operation to
+ // stop at this index.
+ if (attributes == DONT_DELETE) break;
+ // TODO(adamk): Don't fetch the old value if it's an accessor.
+ old_values.Add(Object::GetElement(array, i));
+ indices.Add(isolate->factory()->Uint32ToString(i));
+ }
+
+ MaybeObject* result = array->SetElementsLength(*new_length_handle);
+ Handle<Object> hresult;
+ if (!result->ToHandle(&hresult)) return result;
+
+ CHECK(array->length()->ToArrayIndex(&new_length));
+ if (old_length != new_length) {
+ for (int i = 0; i < indices.length(); ++i) {
+ JSObject::EnqueueChangeRecord(
+ array, "deleted", indices[i], old_values[i]);
+ }
+ JSObject::EnqueueChangeRecord(
+ array, "updated", isolate->factory()->length_symbol(),
+ old_length_handle);
+ }
+ return *hresult;
+}
+
+
MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
Isolate* isolate = object->GetIsolate();
@@ -118,7 +153,7 @@ MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
HandleScope scope(isolate);
// Protect raw pointers.
- Handle<JSObject> object_handle(object, isolate);
+ Handle<JSArray> array_handle(JSArray::cast(object), isolate);
Handle<Object> value_handle(value, isolate);
bool has_exception;
@@ -128,7 +163,11 @@ MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
if (has_exception) return Failure::Exception();
if (uint32_v->Number() == number_v->Number()) {
- return Handle<JSArray>::cast(object_handle)->SetElementsLength(*uint32_v);
+ if (FLAG_harmony_observation && array_handle->map()->is_observed()) {
+ return ArraySetLengthObserved(isolate, array_handle, uint32_v);
+ } else {
+ return array_handle->SetElementsLength(*uint32_v);
+ }
}
return isolate->Throw(
*isolate->factory()->NewRangeError("invalid_array_length",
@@ -448,15 +487,12 @@ const AccessorDescriptor Accessors::ScriptEvalFromFunctionName = {
MaybeObject* Accessors::FunctionGetPrototype(Object* object, void*) {
Heap* heap = Isolate::Current()->heap();
- bool found_it = false;
- JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
- if (!found_it) return heap->undefined_value();
+ JSFunction* function = FindInstanceOf<JSFunction>(object);
+ if (function == NULL) return heap->undefined_value();
while (!function->should_have_prototype()) {
- found_it = false;
- function = FindInPrototypeChain<JSFunction>(object->GetPrototype(),
- &found_it);
+ function = FindInstanceOf<JSFunction>(function->GetPrototype());
// There has to be one because we hit the getter.
- ASSERT(found_it);
+ ASSERT(function != NULL);
}
if (!function->has_prototype()) {
@@ -477,9 +513,8 @@ MaybeObject* Accessors::FunctionSetPrototype(JSObject* object,
Object* value,
void*) {
Heap* heap = object->GetHeap();
- bool found_it = false;
- JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
- if (!found_it) return heap->undefined_value();
+ JSFunction* function = FindInstanceOf<JSFunction>(object);
+ if (function == NULL) return heap->undefined_value();
if (!function->should_have_prototype()) {
// Since we hit this accessor, object will have no prototype property.
return object->SetLocalPropertyIgnoreAttributes(heap->prototype_symbol(),
@@ -509,22 +544,20 @@ const AccessorDescriptor Accessors::FunctionPrototype = {
MaybeObject* Accessors::FunctionGetLength(Object* object, void*) {
- bool found_it = false;
- JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
- if (!found_it) return Smi::FromInt(0);
+ JSFunction* function = FindInstanceOf<JSFunction>(object);
+ if (function == NULL) return Smi::FromInt(0);
// Check if already compiled.
- if (!function->shared()->is_compiled()) {
- // If the function isn't compiled yet, the length is not computed
- // correctly yet. Compile it now and return the right length.
- HandleScope scope;
- Handle<JSFunction> handle(function);
- if (!JSFunction::CompileLazy(handle, KEEP_EXCEPTION)) {
- return Failure::Exception();
- }
- return Smi::FromInt(handle->shared()->length());
- } else {
+ if (function->shared()->is_compiled()) {
return Smi::FromInt(function->shared()->length());
}
+ // If the function isn't compiled yet, the length is not computed correctly
+ // yet. Compile it now and return the right length.
+ HandleScope scope;
+ Handle<JSFunction> handle(function);
+ if (JSFunction::CompileLazy(handle, KEEP_EXCEPTION)) {
+ return Smi::FromInt(handle->shared()->length());
+ }
+ return Failure::Exception();
}
@@ -541,10 +574,8 @@ const AccessorDescriptor Accessors::FunctionLength = {
MaybeObject* Accessors::FunctionGetName(Object* object, void*) {
- bool found_it = false;
- JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
- if (!found_it) return HEAP->undefined_value();
- return holder->shared()->name();
+ JSFunction* holder = FindInstanceOf<JSFunction>(object);
+ return holder == NULL ? HEAP->undefined_value() : holder->shared()->name();
}
@@ -589,9 +620,8 @@ static MaybeObject* ConstructArgumentsObjectForInlinedFunction(
MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) {
Isolate* isolate = Isolate::Current();
HandleScope scope(isolate);
- bool found_it = false;
- JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
- if (!found_it) return isolate->heap()->undefined_value();
+ JSFunction* holder = FindInstanceOf<JSFunction>(object);
+ if (holder == NULL) return isolate->heap()->undefined_value();
Handle<JSFunction> function(holder, isolate);
if (function->shared()->native()) return isolate->heap()->null_value();
@@ -727,9 +757,8 @@ MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
Isolate* isolate = Isolate::Current();
HandleScope scope(isolate);
AssertNoAllocation no_alloc;
- bool found_it = false;
- JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
- if (!found_it) return isolate->heap()->undefined_value();
+ JSFunction* holder = FindInstanceOf<JSFunction>(object);
+ if (holder == NULL) return isolate->heap()->undefined_value();
if (holder->shared()->native()) return isolate->heap()->null_value();
Handle<JSFunction> function(holder, isolate);
@@ -755,6 +784,9 @@ MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
caller = potential_caller;
potential_caller = it.next();
}
+ if (!caller->shared()->native() && potential_caller != NULL) {
+ caller = potential_caller;
+ }
// If caller is bound, return null. This is compatible with JSC, and
// allows us to make bound functions use the strict function map
// and its associated throwing caller and arguments.
@@ -802,4 +834,69 @@ const AccessorDescriptor Accessors::ObjectPrototype = {
0
};
+
+//
+// Accessors::MakeModuleExport
+//
+
+static v8::Handle<v8::Value> ModuleGetExport(
+ v8::Local<v8::String> property,
+ const v8::AccessorInfo& info) {
+ JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
+ Context* context = Context::cast(instance->context());
+ ASSERT(context->IsModuleContext());
+ int slot = info.Data()->Int32Value();
+ Object* value = context->get(slot);
+ if (value->IsTheHole()) {
+ Handle<String> name = v8::Utils::OpenHandle(*property);
+ Isolate* isolate = instance->GetIsolate();
+ isolate->ScheduleThrow(
+ *isolate->factory()->NewReferenceError("not_defined",
+ HandleVector(&name, 1)));
+ return v8::Handle<v8::Value>();
+ }
+ return v8::Utils::ToLocal(Handle<Object>(value));
+}
+
+
+static void ModuleSetExport(
+ v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo& info) {
+ JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder()));
+ Context* context = Context::cast(instance->context());
+ ASSERT(context->IsModuleContext());
+ int slot = info.Data()->Int32Value();
+ Object* old_value = context->get(slot);
+ if (old_value->IsTheHole()) {
+ Handle<String> name = v8::Utils::OpenHandle(*property);
+ Isolate* isolate = instance->GetIsolate();
+ isolate->ScheduleThrow(
+ *isolate->factory()->NewReferenceError("not_defined",
+ HandleVector(&name, 1)));
+ return;
+ }
+ context->set(slot, *v8::Utils::OpenHandle(*value));
+}
+
+
+Handle<AccessorInfo> Accessors::MakeModuleExport(
+ Handle<String> name,
+ int index,
+ PropertyAttributes attributes) {
+ Factory* factory = name->GetIsolate()->factory();
+ Handle<AccessorInfo> info = factory->NewAccessorInfo();
+ info->set_property_attributes(attributes);
+ info->set_all_can_read(true);
+ info->set_all_can_write(true);
+ info->set_name(*name);
+ info->set_data(Smi::FromInt(index));
+ Handle<Object> getter = v8::FromCData(&ModuleGetExport);
+ Handle<Object> setter = v8::FromCData(&ModuleSetExport);
+ info->set_getter(*getter);
+ if (!(attributes & ReadOnly)) info->set_setter(*setter);
+ return info;
+}
+
+
} } // namespace v8::internal