Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: src/objects.cc

Issue 1909433003: Remove support for Object.observe (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebased Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <sstream> 9 #include <sstream>
10 10
(...skipping 2603 matching lines...) Expand 10 before | Expand all | Expand 10 after
2614 } else { 2614 } else {
2615 Handle<NameDictionary> dict(object->property_dictionary()); 2615 Handle<NameDictionary> dict(object->property_dictionary());
2616 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); 2616 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
2617 Handle<NameDictionary> result = 2617 Handle<NameDictionary> result =
2618 NameDictionary::Add(dict, name, value, details); 2618 NameDictionary::Add(dict, name, value, details);
2619 if (*dict != *result) object->set_properties(*result); 2619 if (*dict != *result) object->set_properties(*result);
2620 } 2620 }
2621 } 2621 }
2622 2622
2623 2623
2624 MaybeHandle<Object> JSObject::EnqueueChangeRecord(Handle<JSObject> object,
2625 const char* type_str,
2626 Handle<Name> name,
2627 Handle<Object> old_value) {
2628 DCHECK(!object->IsJSGlobalProxy());
2629 DCHECK(!object->IsJSGlobalObject());
2630 Isolate* isolate = object->GetIsolate();
2631 HandleScope scope(isolate);
2632 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
2633 Handle<Object> args[] = { type, object, name, old_value };
2634 int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
2635
2636 return Execution::Call(isolate,
2637 Handle<JSFunction>(isolate->observers_notify_change()),
2638 isolate->factory()->undefined_value(), argc, args);
2639 }
2640
2641
2642 const char* Representation::Mnemonic() const { 2624 const char* Representation::Mnemonic() const {
2643 switch (kind_) { 2625 switch (kind_) {
2644 case kNone: return "v"; 2626 case kNone: return "v";
2645 case kTagged: return "t"; 2627 case kTagged: return "t";
2646 case kSmi: return "s"; 2628 case kSmi: return "s";
2647 case kDouble: return "d"; 2629 case kDouble: return "d";
2648 case kInteger32: return "i"; 2630 case kInteger32: return "i";
2649 case kHeapObject: return "h"; 2631 case kHeapObject: return "h";
2650 case kExternal: return "x"; 2632 case kExternal: return "x";
2651 default: 2633 default:
(...skipping 1731 matching lines...) Expand 10 before | Expand all | Expand 10 after
4383 4365
4384 4366
4385 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) { 4367 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
4386 // Proxies are handled elsewhere. Other non-JSObjects cannot have own 4368 // Proxies are handled elsewhere. Other non-JSObjects cannot have own
4387 // properties. 4369 // properties.
4388 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); 4370 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
4389 4371
4390 // Store on the holder which may be hidden behind the receiver. 4372 // Store on the holder which may be hidden behind the receiver.
4391 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); 4373 DCHECK(it->HolderIsReceiverOrHiddenPrototype());
4392 4374
4393 // Old value for the observation change record.
4394 // Fetch before transforming the object since the encoding may become
4395 // incompatible with what's cached in |it|.
4396 bool is_observed = receiver->map()->is_observed() &&
4397 (it->IsElement() || !it->name()->IsPrivate());
4398 MaybeHandle<Object> maybe_old;
4399 if (is_observed) maybe_old = it->GetDataValue();
4400
4401 Handle<Object> to_assign = value; 4375 Handle<Object> to_assign = value;
4402 // Convert the incoming value to a number for storing into typed arrays. 4376 // Convert the incoming value to a number for storing into typed arrays.
4403 if (it->IsElement() && receiver->HasFixedTypedArrayElements()) { 4377 if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
4404 if (!value->IsNumber() && !value->IsUndefined()) { 4378 if (!value->IsNumber() && !value->IsUndefined()) {
4405 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4379 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
4406 it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>()); 4380 it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>());
4407 // We have to recheck the length. However, it can only change if the 4381 // We have to recheck the length. However, it can only change if the
4408 // underlying buffer was neutered, so just check that. 4382 // underlying buffer was neutered, so just check that.
4409 if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) { 4383 if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
4410 return Just(true); 4384 return Just(true);
4411 // TODO(neis): According to the spec, this should throw a TypeError. 4385 // TODO(neis): According to the spec, this should throw a TypeError.
4412 } 4386 }
4413 } 4387 }
4414 } 4388 }
4415 4389
4416 // Possibly migrate to the most up-to-date map that will be able to store 4390 // Possibly migrate to the most up-to-date map that will be able to store
4417 // |value| under it->name(). 4391 // |value| under it->name().
4418 it->PrepareForDataProperty(to_assign); 4392 it->PrepareForDataProperty(to_assign);
4419 4393
4420 // Write the property value. 4394 // Write the property value.
4421 it->WriteDataValue(to_assign); 4395 it->WriteDataValue(to_assign);
4422 4396
4423 // Send the change record if there are observers.
4424 if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
4425 RETURN_ON_EXCEPTION_VALUE(
4426 it->isolate(),
4427 JSObject::EnqueueChangeRecord(receiver, "update", it->GetName(),
4428 maybe_old.ToHandleChecked()),
4429 Nothing<bool>());
4430 }
4431
4432 #if VERIFY_HEAP 4397 #if VERIFY_HEAP
4433 if (FLAG_verify_heap) { 4398 if (FLAG_verify_heap) {
4434 receiver->JSObjectVerify(); 4399 receiver->JSObjectVerify();
4435 } 4400 }
4436 #endif 4401 #endif
4437 return Just(true); 4402 return Just(true);
4438 } 4403 }
4439 4404
4440 4405
4441 MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
4442 Handle<JSArray> object) {
4443 Isolate* isolate = object->GetIsolate();
4444 HandleScope scope(isolate);
4445 Handle<Object> args[] = {object};
4446
4447 return Execution::Call(
4448 isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
4449 isolate->factory()->undefined_value(), arraysize(args), args);
4450 }
4451
4452
4453 MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
4454 Handle<JSArray> object) {
4455 Isolate* isolate = object->GetIsolate();
4456 HandleScope scope(isolate);
4457 Handle<Object> args[] = {object};
4458
4459 return Execution::Call(
4460 isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
4461 isolate->factory()->undefined_value(), arraysize(args), args);
4462 }
4463
4464
4465 MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
4466 Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
4467 uint32_t add_count) {
4468 Isolate* isolate = object->GetIsolate();
4469 HandleScope scope(isolate);
4470 Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
4471 Handle<Object> add_count_object =
4472 isolate->factory()->NewNumberFromUint(add_count);
4473
4474 Handle<Object> args[] = {object, index_object, deleted, add_count_object};
4475
4476 return Execution::Call(
4477 isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
4478 isolate->factory()->undefined_value(), arraysize(args), args);
4479 }
4480
4481
4482 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value, 4406 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
4483 PropertyAttributes attributes, 4407 PropertyAttributes attributes,
4484 ShouldThrow should_throw, 4408 ShouldThrow should_throw,
4485 StoreFromKeyed store_mode) { 4409 StoreFromKeyed store_mode) {
4486 if (!it->GetReceiver()->IsJSObject()) { 4410 if (!it->GetReceiver()->IsJSObject()) {
4487 if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) { 4411 if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) {
4488 RETURN_FAILURE(it->isolate(), should_throw, 4412 RETURN_FAILURE(it->isolate(), should_throw,
4489 NewTypeError(MessageTemplate::kProxyPrivate)); 4413 NewTypeError(MessageTemplate::kProxyPrivate));
4490 } 4414 }
4491 return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(), 4415 return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
4542 4466
4543 // TODO(verwaest): Encapsulate dictionary handling better. 4467 // TODO(verwaest): Encapsulate dictionary handling better.
4544 if (receiver->map()->is_dictionary_map()) { 4468 if (receiver->map()->is_dictionary_map()) {
4545 // TODO(dcarney): just populate TransitionPropertyCell here? 4469 // TODO(dcarney): just populate TransitionPropertyCell here?
4546 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); 4470 JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
4547 } else { 4471 } else {
4548 // Write the property value. 4472 // Write the property value.
4549 it->WriteDataValue(value); 4473 it->WriteDataValue(value);
4550 } 4474 }
4551 4475
4552 // Send the change record if there are observers.
4553 if (receiver->map()->is_observed() && !it->name()->IsPrivate()) {
4554 RETURN_ON_EXCEPTION_VALUE(isolate, JSObject::EnqueueChangeRecord(
4555 receiver, "add", it->name(),
4556 it->factory()->the_hole_value()),
4557 Nothing<bool>());
4558 }
4559 #if VERIFY_HEAP 4476 #if VERIFY_HEAP
4560 if (FLAG_verify_heap) { 4477 if (FLAG_verify_heap) {
4561 receiver->JSObjectVerify(); 4478 receiver->JSObjectVerify();
4562 } 4479 }
4563 #endif 4480 #endif
4564 } 4481 }
4565 4482
4566 return Just(true); 4483 return Just(true);
4567 } 4484 }
4568 4485
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after
5304 it, value, attributes, THROW_ON_ERROR, handling)); 5221 it, value, attributes, THROW_ON_ERROR, handling));
5305 return value; 5222 return value;
5306 } 5223 }
5307 5224
5308 5225
5309 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes( 5226 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
5310 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, 5227 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
5311 ShouldThrow should_throw, AccessorInfoHandling handling) { 5228 ShouldThrow should_throw, AccessorInfoHandling handling) {
5312 it->UpdateProtector(); 5229 it->UpdateProtector();
5313 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); 5230 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
5314 bool is_observed = object->map()->is_observed() &&
5315 (it->IsElement() || !it->name()->IsPrivate());
5316 5231
5317 for (; it->IsFound(); it->Next()) { 5232 for (; it->IsFound(); it->Next()) {
5318 switch (it->state()) { 5233 switch (it->state()) {
5319 case LookupIterator::JSPROXY: 5234 case LookupIterator::JSPROXY:
5320 case LookupIterator::NOT_FOUND: 5235 case LookupIterator::NOT_FOUND:
5321 case LookupIterator::TRANSITION: 5236 case LookupIterator::TRANSITION:
5322 UNREACHABLE(); 5237 UNREACHABLE();
5323 5238
5324 case LookupIterator::ACCESS_CHECK: 5239 case LookupIterator::ACCESS_CHECK:
5325 if (!it->HasAccess()) { 5240 if (!it->HasAccess()) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
5365 JSObject::SetPropertyWithAccessor(it, value, should_throw); 5280 JSObject::SetPropertyWithAccessor(it, value, should_throw);
5366 5281
5367 if (current_attributes == attributes || result.IsNothing()) { 5282 if (current_attributes == attributes || result.IsNothing()) {
5368 return result; 5283 return result;
5369 } 5284 }
5370 5285
5371 } else { 5286 } else {
5372 it->ReconfigureDataProperty(value, attributes); 5287 it->ReconfigureDataProperty(value, attributes);
5373 } 5288 }
5374 5289
5375 if (is_observed) {
5376 RETURN_ON_EXCEPTION_VALUE(
5377 it->isolate(),
5378 EnqueueChangeRecord(object, "reconfigure", it->GetName(),
5379 it->factory()->the_hole_value()),
5380 Nothing<bool>());
5381 }
5382
5383 return Just(true); 5290 return Just(true);
5384 } 5291 }
5385 case LookupIterator::INTEGER_INDEXED_EXOTIC: 5292 case LookupIterator::INTEGER_INDEXED_EXOTIC:
5386 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value, 5293 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value,
5387 should_throw); 5294 should_throw);
5388 5295
5389 case LookupIterator::DATA: { 5296 case LookupIterator::DATA: {
5390 // Regular property update if the attributes match. 5297 // Regular property update if the attributes match.
5391 if (it->property_attributes() == attributes) { 5298 if (it->property_attributes() == attributes) {
5392 return SetDataProperty(it, value); 5299 return SetDataProperty(it, value);
5393 } 5300 }
5394 5301
5395 // Special case: properties of typed arrays cannot be reconfigured to 5302 // Special case: properties of typed arrays cannot be reconfigured to
5396 // non-writable nor to non-enumerable. 5303 // non-writable nor to non-enumerable.
5397 if (it->IsElement() && object->HasFixedTypedArrayElements()) { 5304 if (it->IsElement() && object->HasFixedTypedArrayElements()) {
5398 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), 5305 return RedefineIncompatibleProperty(it->isolate(), it->GetName(),
5399 value, should_throw); 5306 value, should_throw);
5400 } 5307 }
5401 5308
5402 // Reconfigure the data property if the attributes mismatch. 5309 // Reconfigure the data property if the attributes mismatch.
5403 Handle<Object> old_value = it->factory()->the_hole_value();
5404 if (is_observed) old_value = it->GetDataValue();
5405
5406 it->ReconfigureDataProperty(value, attributes); 5310 it->ReconfigureDataProperty(value, attributes);
5407 5311
5408 if (is_observed) {
5409 if (old_value->SameValue(*value)) {
5410 old_value = it->factory()->the_hole_value();
5411 }
5412 RETURN_ON_EXCEPTION_VALUE(
5413 it->isolate(), EnqueueChangeRecord(object, "reconfigure",
5414 it->GetName(), old_value),
5415 Nothing<bool>());
5416 }
5417 return Just(true); 5312 return Just(true);
5418 } 5313 }
5419 } 5314 }
5420 } 5315 }
5421 5316
5422 return AddDataProperty(it, value, attributes, should_throw, 5317 return AddDataProperty(it, value, attributes, should_throw,
5423 CERTAINLY_NOT_STORE_FROM_KEYED); 5318 CERTAINLY_NOT_STORE_FROM_KEYED);
5424 } 5319 }
5425 5320
5426 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( 5321 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after
6136 if (it->GetReceiver()->IsJSProxy()) { 6031 if (it->GetReceiver()->IsJSProxy()) {
6137 if (it->state() != LookupIterator::NOT_FOUND) { 6032 if (it->state() != LookupIterator::NOT_FOUND) {
6138 DCHECK_EQ(LookupIterator::DATA, it->state()); 6033 DCHECK_EQ(LookupIterator::DATA, it->state());
6139 DCHECK(it->name()->IsPrivate()); 6034 DCHECK(it->name()->IsPrivate());
6140 it->Delete(); 6035 it->Delete();
6141 } 6036 }
6142 return Just(true); 6037 return Just(true);
6143 } 6038 }
6144 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); 6039 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
6145 6040
6146 bool is_observed = receiver->map()->is_observed() &&
6147 (it->IsElement() || !it->name()->IsPrivate());
6148
6149 Handle<Object> old_value = it->factory()->the_hole_value();
6150
6151 for (; it->IsFound(); it->Next()) { 6041 for (; it->IsFound(); it->Next()) {
6152 switch (it->state()) { 6042 switch (it->state()) {
6153 case LookupIterator::JSPROXY: 6043 case LookupIterator::JSPROXY:
6154 case LookupIterator::NOT_FOUND: 6044 case LookupIterator::NOT_FOUND:
6155 case LookupIterator::TRANSITION: 6045 case LookupIterator::TRANSITION:
6156 UNREACHABLE(); 6046 UNREACHABLE();
6157 case LookupIterator::ACCESS_CHECK: 6047 case LookupIterator::ACCESS_CHECK:
6158 if (it->HasAccess()) break; 6048 if (it->HasAccess()) break;
6159 isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()); 6049 isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
6160 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 6050 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
6161 return Just(false); 6051 return Just(false);
6162 case LookupIterator::INTERCEPTOR: { 6052 case LookupIterator::INTERCEPTOR: {
6163 ShouldThrow should_throw = 6053 ShouldThrow should_throw =
6164 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; 6054 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
6165 Maybe<bool> result = 6055 Maybe<bool> result =
6166 JSObject::DeletePropertyWithInterceptor(it, should_throw); 6056 JSObject::DeletePropertyWithInterceptor(it, should_throw);
6167 // An exception was thrown in the interceptor. Propagate. 6057 // An exception was thrown in the interceptor. Propagate.
6168 if (isolate->has_pending_exception()) return Nothing<bool>(); 6058 if (isolate->has_pending_exception()) return Nothing<bool>();
6169 // Delete with interceptor succeeded. Return result. 6059 // Delete with interceptor succeeded. Return result.
6170 // TODO(neis): In strict mode, we should probably throw if the 6060 // TODO(neis): In strict mode, we should probably throw if the
6171 // interceptor returns false. 6061 // interceptor returns false.
6172 if (result.IsJust()) return result; 6062 if (result.IsJust()) return result;
6173 break; 6063 break;
6174 } 6064 }
6175 case LookupIterator::INTEGER_INDEXED_EXOTIC: 6065 case LookupIterator::INTEGER_INDEXED_EXOTIC:
6176 return Just(true); 6066 return Just(true);
6177 case LookupIterator::DATA: 6067 case LookupIterator::DATA:
6178 if (is_observed) {
6179 old_value = it->GetDataValue();
6180 }
6181 // Fall through.
6182 case LookupIterator::ACCESSOR: { 6068 case LookupIterator::ACCESSOR: {
6183 if (!it->IsConfigurable()) { 6069 if (!it->IsConfigurable()) {
6184 // Fail if the property is not configurable. 6070 // Fail if the property is not configurable.
6185 if (is_strict(language_mode)) { 6071 if (is_strict(language_mode)) {
6186 isolate->Throw(*isolate->factory()->NewTypeError( 6072 isolate->Throw(*isolate->factory()->NewTypeError(
6187 MessageTemplate::kStrictDeleteProperty, it->GetName(), 6073 MessageTemplate::kStrictDeleteProperty, it->GetName(),
6188 receiver)); 6074 receiver));
6189 return Nothing<bool>(); 6075 return Nothing<bool>();
6190 } 6076 }
6191 return Just(false); 6077 return Just(false);
6192 } 6078 }
6193 6079
6194 it->Delete(); 6080 it->Delete();
6195 6081
6196 if (is_observed) {
6197 RETURN_ON_EXCEPTION_VALUE(
6198 isolate, JSObject::EnqueueChangeRecord(receiver, "delete",
6199 it->GetName(), old_value),
6200 Nothing<bool>());
6201 }
6202
6203 return Just(true); 6082 return Just(true);
6204 } 6083 }
6205 } 6084 }
6206 } 6085 }
6207 6086
6208 return Just(true); 6087 return Just(true);
6209 } 6088 }
6210 6089
6211 6090
6212 Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index, 6091 Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index,
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after
6941 new_writable = true; 6820 new_writable = true;
6942 } else { 6821 } else {
6943 // 15. Else, 6822 // 15. Else,
6944 // 15a. Need to defer setting the [[Writable]] attribute to false in case 6823 // 15a. Need to defer setting the [[Writable]] attribute to false in case
6945 // any elements cannot be deleted. 6824 // any elements cannot be deleted.
6946 // 15b. Let newWritable be false. (It's initialized as "false" anyway.) 6825 // 15b. Let newWritable be false. (It's initialized as "false" anyway.)
6947 // 15c. Set newLenDesc.[[Writable]] to true. 6826 // 15c. Set newLenDesc.[[Writable]] to true.
6948 // (Not needed.) 6827 // (Not needed.)
6949 } 6828 }
6950 // Most of steps 16 through 19 is implemented by JSArray::SetLength. 6829 // Most of steps 16 through 19 is implemented by JSArray::SetLength.
6951 if (JSArray::ObservableSetLength(a, new_len).is_null()) { 6830 JSArray::SetLength(a, new_len);
6952 DCHECK(isolate->has_pending_exception());
6953 return Nothing<bool>();
6954 }
6955 // Steps 19d-ii, 20. 6831 // Steps 19d-ii, 20.
6956 if (!new_writable) { 6832 if (!new_writable) {
6957 PropertyDescriptor readonly; 6833 PropertyDescriptor readonly;
6958 readonly.set_writable(false); 6834 readonly.set_writable(false);
6959 Maybe<bool> success = OrdinaryDefineOwnProperty( 6835 Maybe<bool> success = OrdinaryDefineOwnProperty(
6960 isolate, a, isolate->factory()->length_string(), &readonly, 6836 isolate, a, isolate->factory()->length_string(), &readonly,
6961 should_throw); 6837 should_throw);
6962 DCHECK(success.FromJust()); 6838 DCHECK(success.FromJust());
6963 USE(success); 6839 USE(success);
6964 } 6840 }
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
7451 } 7327 }
7452 7328
7453 7329
7454 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver, 7330 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver,
7455 IntegrityLevel level, 7331 IntegrityLevel level,
7456 ShouldThrow should_throw) { 7332 ShouldThrow should_throw) {
7457 DCHECK(level == SEALED || level == FROZEN); 7333 DCHECK(level == SEALED || level == FROZEN);
7458 7334
7459 if (receiver->IsJSObject()) { 7335 if (receiver->IsJSObject()) {
7460 Handle<JSObject> object = Handle<JSObject>::cast(receiver); 7336 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
7461 if (!object->HasSloppyArgumentsElements() && 7337 if (!object->HasSloppyArgumentsElements()) { // Fast path.
7462 !object->map()->is_observed()) { // Fast path.
7463 if (level == SEALED) { 7338 if (level == SEALED) {
7464 return JSObject::PreventExtensionsWithTransition<SEALED>(object, 7339 return JSObject::PreventExtensionsWithTransition<SEALED>(object,
7465 should_throw); 7340 should_throw);
7466 } else { 7341 } else {
7467 return JSObject::PreventExtensionsWithTransition<FROZEN>(object, 7342 return JSObject::PreventExtensionsWithTransition<FROZEN>(object,
7468 should_throw); 7343 should_throw);
7469 } 7344 }
7470 } 7345 }
7471 } 7346 }
7472 7347
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
7603 return Nothing<bool>(); 7478 return Nothing<bool>();
7604 } 7479 }
7605 return Just(true); 7480 return Just(true);
7606 } 7481 }
7607 7482
7608 7483
7609 Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object, 7484 Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
7610 ShouldThrow should_throw) { 7485 ShouldThrow should_throw) {
7611 Isolate* isolate = object->GetIsolate(); 7486 Isolate* isolate = object->GetIsolate();
7612 7487
7613 if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) { 7488 if (!object->HasSloppyArgumentsElements()) {
7614 return PreventExtensionsWithTransition<NONE>(object, should_throw); 7489 return PreventExtensionsWithTransition<NONE>(object, should_throw);
7615 } 7490 }
7616 7491
7617 if (object->IsAccessCheckNeeded() && 7492 if (object->IsAccessCheckNeeded() &&
7618 !isolate->MayAccess(handle(isolate->context()), object)) { 7493 !isolate->MayAccess(handle(isolate->context()), object)) {
7619 isolate->ReportFailedAccessCheck(object); 7494 isolate->ReportFailedAccessCheck(object);
7620 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 7495 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7621 RETURN_FAILURE(isolate, should_throw, 7496 RETURN_FAILURE(isolate, should_throw,
7622 NewTypeError(MessageTemplate::kNoAccess)); 7497 NewTypeError(MessageTemplate::kNoAccess));
7623 } 7498 }
(...skipping 20 matching lines...) Expand all
7644 7519
7645 // Do a map transition, other objects with this map may still 7520 // Do a map transition, other objects with this map may still
7646 // be extensible. 7521 // be extensible.
7647 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. 7522 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
7648 Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions"); 7523 Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions");
7649 7524
7650 new_map->set_is_extensible(false); 7525 new_map->set_is_extensible(false);
7651 JSObject::MigrateToMap(object, new_map); 7526 JSObject::MigrateToMap(object, new_map);
7652 DCHECK(!object->map()->is_extensible()); 7527 DCHECK(!object->map()->is_extensible());
7653 7528
7654 if (object->map()->is_observed()) {
7655 RETURN_ON_EXCEPTION_VALUE(
7656 isolate,
7657 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
7658 isolate->factory()->the_hole_value()),
7659 Nothing<bool>());
7660 }
7661 return Just(true); 7529 return Just(true);
7662 } 7530 }
7663 7531
7664 7532
7665 Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) { 7533 Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) {
7666 if (object->IsJSProxy()) { 7534 if (object->IsJSProxy()) {
7667 return JSProxy::IsExtensible(Handle<JSProxy>::cast(object)); 7535 return JSProxy::IsExtensible(Handle<JSProxy>::cast(object));
7668 } 7536 }
7669 return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object))); 7537 return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object)));
7670 } 7538 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
7751 } 7619 }
7752 7620
7753 7621
7754 template <PropertyAttributes attrs> 7622 template <PropertyAttributes attrs>
7755 Maybe<bool> JSObject::PreventExtensionsWithTransition( 7623 Maybe<bool> JSObject::PreventExtensionsWithTransition(
7756 Handle<JSObject> object, ShouldThrow should_throw) { 7624 Handle<JSObject> object, ShouldThrow should_throw) {
7757 STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN); 7625 STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
7758 7626
7759 // Sealing/freezing sloppy arguments should be handled elsewhere. 7627 // Sealing/freezing sloppy arguments should be handled elsewhere.
7760 DCHECK(!object->HasSloppyArgumentsElements()); 7628 DCHECK(!object->HasSloppyArgumentsElements());
7761 DCHECK(!object->map()->is_observed());
7762 7629
7763 Isolate* isolate = object->GetIsolate(); 7630 Isolate* isolate = object->GetIsolate();
7764 if (object->IsAccessCheckNeeded() && 7631 if (object->IsAccessCheckNeeded() &&
7765 !isolate->MayAccess(handle(isolate->context()), object)) { 7632 !isolate->MayAccess(handle(isolate->context()), object)) {
7766 isolate->ReportFailedAccessCheck(object); 7633 isolate->ReportFailedAccessCheck(object);
7767 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 7634 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
7768 RETURN_FAILURE(isolate, should_throw, 7635 RETURN_FAILURE(isolate, should_throw,
7769 NewTypeError(MessageTemplate::kNoAccess)); 7636 NewTypeError(MessageTemplate::kNoAccess));
7770 } 7637 }
7771 7638
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
7870 object->RequireSlowElements(dictionary); 7737 object->RequireSlowElements(dictionary);
7871 if (attrs != NONE) { 7738 if (attrs != NONE) {
7872 ApplyAttributesToDictionary(dictionary, attrs); 7739 ApplyAttributesToDictionary(dictionary, attrs);
7873 } 7740 }
7874 } 7741 }
7875 7742
7876 return Just(true); 7743 return Just(true);
7877 } 7744 }
7878 7745
7879 7746
7880 void JSObject::SetObserved(Handle<JSObject> object) {
7881 DCHECK(!object->IsJSGlobalProxy());
7882 DCHECK(!object->IsJSGlobalObject());
7883 Isolate* isolate = object->GetIsolate();
7884 Handle<Map> new_map;
7885 Handle<Map> old_map(object->map(), isolate);
7886 DCHECK(!old_map->is_observed());
7887 Map* transition = TransitionArray::SearchSpecial(
7888 *old_map, isolate->heap()->observed_symbol());
7889 if (transition != NULL) {
7890 new_map = handle(transition, isolate);
7891 DCHECK(new_map->is_observed());
7892 } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
7893 new_map = Map::CopyForObserved(old_map);
7894 } else {
7895 new_map = Map::Copy(old_map, "SlowObserved");
7896 new_map->set_is_observed();
7897 }
7898 JSObject::MigrateToMap(object, new_map);
7899 }
7900
7901
7902 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object, 7747 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
7903 Representation representation, 7748 Representation representation,
7904 FieldIndex index) { 7749 FieldIndex index) {
7905 Isolate* isolate = object->GetIsolate(); 7750 Isolate* isolate = object->GetIsolate();
7906 if (object->IsUnboxedDoubleField(index)) { 7751 if (object->IsUnboxedDoubleField(index)) {
7907 double value = object->RawFastDoublePropertyAt(index); 7752 double value = object->RawFastDoublePropertyAt(index);
7908 return isolate->factory()->NewHeapNumber(value); 7753 return isolate->factory()->NewHeapNumber(value);
7909 } 7754 }
7910 Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate); 7755 Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
7911 return Object::WrapForRead(isolate, raw_value, representation); 7756 return Object::WrapForRead(isolate, raw_value, representation);
(...skipping 1077 matching lines...) Expand 10 before | Expand all | Expand 10 after
8989 } 8834 }
8990 it->Next(); 8835 it->Next();
8991 } 8836 }
8992 8837
8993 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); 8838 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
8994 // Ignore accessors on typed arrays. 8839 // Ignore accessors on typed arrays.
8995 if (it->IsElement() && object->HasFixedTypedArrayElements()) { 8840 if (it->IsElement() && object->HasFixedTypedArrayElements()) {
8996 return it->factory()->undefined_value(); 8841 return it->factory()->undefined_value();
8997 } 8842 }
8998 8843
8999 Handle<Object> old_value = isolate->factory()->the_hole_value();
9000 bool is_observed = object->map()->is_observed() &&
9001 (it->IsElement() || !it->name()->IsPrivate());
9002 bool preexists = false;
9003 if (is_observed) {
9004 CHECK(GetPropertyAttributes(it).IsJust());
9005 preexists = it->IsFound();
9006 if (preexists && (it->state() == LookupIterator::DATA ||
9007 it->GetAccessors()->IsAccessorInfo())) {
9008 old_value = Object::GetProperty(it).ToHandleChecked();
9009 }
9010 }
9011
9012 DCHECK(getter->IsCallable() || getter->IsUndefined() || getter->IsNull() || 8844 DCHECK(getter->IsCallable() || getter->IsUndefined() || getter->IsNull() ||
9013 getter->IsFunctionTemplateInfo()); 8845 getter->IsFunctionTemplateInfo());
9014 DCHECK(setter->IsCallable() || setter->IsUndefined() || setter->IsNull() || 8846 DCHECK(setter->IsCallable() || setter->IsUndefined() || setter->IsNull() ||
9015 getter->IsFunctionTemplateInfo()); 8847 getter->IsFunctionTemplateInfo());
9016 // At least one of the accessors needs to be a new value. 8848 // At least one of the accessors needs to be a new value.
9017 DCHECK(!getter->IsNull() || !setter->IsNull()); 8849 DCHECK(!getter->IsNull() || !setter->IsNull());
9018 if (!getter->IsNull()) { 8850 if (!getter->IsNull()) {
9019 it->TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes); 8851 it->TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
9020 } 8852 }
9021 if (!setter->IsNull()) { 8853 if (!setter->IsNull()) {
9022 it->TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes); 8854 it->TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
9023 } 8855 }
9024 8856
9025 if (is_observed) {
9026 // Make sure the top context isn't changed.
9027 AssertNoContextChange ncc(isolate);
9028 const char* type = preexists ? "reconfigure" : "add";
9029 RETURN_ON_EXCEPTION(
9030 isolate, EnqueueChangeRecord(object, type, it->GetName(), old_value),
9031 Object);
9032 }
9033
9034 return isolate->factory()->undefined_value(); 8857 return isolate->factory()->undefined_value();
9035 } 8858 }
9036 8859
9037 8860
9038 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object, 8861 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
9039 Handle<AccessorInfo> info) { 8862 Handle<AccessorInfo> info) {
9040 Isolate* isolate = object->GetIsolate(); 8863 Isolate* isolate = object->GetIsolate();
9041 Handle<Name> name(Name::cast(info->name()), isolate); 8864 Handle<Name> name(Name::cast(info->name()), isolate);
9042 8865
9043 LookupIterator it = LookupIterator::PropertyOrElement( 8866 LookupIterator it = LookupIterator::PropertyOrElement(
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
9632 map->set_prototype(initial_map->prototype()); 9455 map->set_prototype(initial_map->prototype());
9633 9456
9634 if (TransitionArray::CanHaveMoreTransitions(initial_map)) { 9457 if (TransitionArray::CanHaveMoreTransitions(initial_map)) {
9635 Map::ConnectTransition(initial_map, map, transition_symbol, 9458 Map::ConnectTransition(initial_map, map, transition_symbol,
9636 SPECIAL_TRANSITION); 9459 SPECIAL_TRANSITION);
9637 } 9460 }
9638 return map; 9461 return map;
9639 } 9462 }
9640 9463
9641 9464
9642 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
9643 DCHECK(!map->is_observed());
9644
9645 Isolate* isolate = map->GetIsolate();
9646
9647 bool insert_transition =
9648 TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map();
9649
9650 if (insert_transition) {
9651 Handle<Map> new_map = CopyForTransition(map, "CopyForObserved");
9652 new_map->set_is_observed();
9653
9654 Handle<Name> name = isolate->factory()->observed_symbol();
9655 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
9656 return new_map;
9657 }
9658
9659 // Create a new free-floating map only if we are not allowed to store it.
9660 Handle<Map> new_map = Map::Copy(map, "CopyForObserved");
9661 new_map->set_is_observed();
9662 return new_map;
9663 }
9664
9665
9666 Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) { 9465 Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
9667 DCHECK(!map->is_prototype_map()); 9466 DCHECK(!map->is_prototype_map());
9668 Handle<Map> new_map = CopyDropDescriptors(map); 9467 Handle<Map> new_map = CopyDropDescriptors(map);
9669 9468
9670 if (map->owns_descriptors()) { 9469 if (map->owns_descriptors()) {
9671 // In case the map owned its own descriptors, share the descriptors and 9470 // In case the map owned its own descriptors, share the descriptors and
9672 // transfer ownership to the new map. 9471 // transfer ownership to the new map.
9673 // The properties did not change, so reuse descriptors. 9472 // The properties did not change, so reuse descriptors.
9674 new_map->InitializeDescriptors(map->instance_descriptors(), 9473 new_map->InitializeDescriptors(map->instance_descriptors(),
9675 map->GetLayoutDescriptor()); 9474 map->GetLayoutDescriptor());
(...skipping 5040 matching lines...) Expand 10 before | Expand all | Expand 10 after
14716 } 14515 }
14717 14516
14718 // static 14517 // static
14719 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) { 14518 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
14720 DCHECK(capacity >= 0); 14519 DCHECK(capacity >= 0);
14721 array->GetIsolate()->factory()->NewJSArrayStorage( 14520 array->GetIsolate()->factory()->NewJSArrayStorage(
14722 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); 14521 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
14723 } 14522 }
14724 14523
14725 14524
14726 // Returns false if the passed-in index is marked non-configurable, which will
14727 // cause the truncation operation to halt, and thus no further old values need
14728 // be collected.
14729 static bool GetOldValue(Isolate* isolate,
14730 Handle<JSObject> object,
14731 uint32_t index,
14732 List<Handle<Object> >* old_values,
14733 List<uint32_t>* indices) {
14734 LookupIterator it(isolate, object, index, object, LookupIterator::HIDDEN);
14735 CHECK(JSReceiver::GetPropertyAttributes(&it).IsJust());
14736 DCHECK(it.IsFound());
14737 if (!it.IsConfigurable()) return false;
14738 Handle<Object> value =
14739 it.state() == LookupIterator::ACCESSOR
14740 ? Handle<Object>::cast(isolate->factory()->the_hole_value())
14741 : JSReceiver::GetDataProperty(&it);
14742 old_values->Add(value);
14743 indices->Add(index);
14744 return true;
14745 }
14746
14747
14748 void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) { 14525 void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
14749 // We should never end in here with a pixel or external array. 14526 // We should never end in here with a pixel or external array.
14750 DCHECK(array->AllowsSetLength()); 14527 DCHECK(array->AllowsSetLength());
14751 if (array->SetLengthWouldNormalize(new_length)) { 14528 if (array->SetLengthWouldNormalize(new_length)) {
14752 JSObject::NormalizeElements(array); 14529 JSObject::NormalizeElements(array);
14753 } 14530 }
14754 array->GetElementsAccessor()->SetLength(array, new_length); 14531 array->GetElementsAccessor()->SetLength(array, new_length);
14755 } 14532 }
14756 14533
14757 14534
14758 MaybeHandle<Object> JSArray::ObservableSetLength(Handle<JSArray> array,
14759 uint32_t new_length) {
14760 if (!array->map()->is_observed()) {
14761 SetLength(array, new_length);
14762 return array;
14763 }
14764
14765 Isolate* isolate = array->GetIsolate();
14766 List<uint32_t> indices;
14767 List<Handle<Object> > old_values;
14768 Handle<Object> old_length_handle(array->length(), isolate);
14769 uint32_t old_length = 0;
14770 CHECK(old_length_handle->ToArrayLength(&old_length));
14771
14772 int num_elements = array->NumberOfOwnElements(ALL_PROPERTIES);
14773 if (num_elements > 0) {
14774 if (old_length == static_cast<uint32_t>(num_elements)) {
14775 // Simple case for arrays without holes.
14776 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
14777 if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
14778 }
14779 } else {
14780 // For sparse arrays, only iterate over existing elements.
14781 // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
14782 // the to-be-removed indices twice.
14783 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
14784 array->GetOwnElementKeys(*keys, ALL_PROPERTIES);
14785 while (num_elements-- > 0) {
14786 uint32_t index = NumberToUint32(keys->get(num_elements));
14787 if (index < new_length) break;
14788 if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
14789 }
14790 }
14791 }
14792
14793 SetLength(array, new_length);
14794
14795 CHECK(array->length()->ToArrayLength(&new_length));
14796 if (old_length == new_length) return array;
14797
14798 RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
14799
14800 for (int i = 0; i < indices.length(); ++i) {
14801 // For deletions where the property was an accessor, old_values[i]
14802 // will be the hole, which instructs EnqueueChangeRecord to elide
14803 // the "oldValue" property.
14804 RETURN_ON_EXCEPTION(
14805 isolate,
14806 JSObject::EnqueueChangeRecord(
14807 array, "delete", isolate->factory()->Uint32ToString(indices[i]),
14808 old_values[i]),
14809 Object);
14810 }
14811
14812 RETURN_ON_EXCEPTION(isolate,
14813 JSObject::EnqueueChangeRecord(
14814 array, "update", isolate->factory()->length_string(),
14815 old_length_handle),
14816 Object);
14817
14818 RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
14819
14820 uint32_t index = Min(old_length, new_length);
14821 uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
14822 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
14823 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
14824 if (delete_count > 0) {
14825 for (int i = indices.length() - 1; i >= 0; i--) {
14826 // Skip deletions where the property was an accessor, leaving holes
14827 // in the array of old values.
14828 if (old_values[i]->IsTheHole()) continue;
14829 JSObject::AddDataElement(deleted, indices[i] - index, old_values[i], NONE)
14830 .Assert();
14831 }
14832
14833 JSArray::SetLength(deleted, delete_count);
14834 }
14835
14836 RETURN_ON_EXCEPTION(
14837 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
14838
14839 return array;
14840 }
14841
14842
14843 // static 14535 // static
14844 void Map::AddDependentCode(Handle<Map> map, 14536 void Map::AddDependentCode(Handle<Map> map,
14845 DependentCode::DependencyGroup group, 14537 DependentCode::DependencyGroup group,
14846 Handle<Code> code) { 14538 Handle<Code> code) {
14847 Handle<WeakCell> cell = Code::WeakCellFor(code); 14539 Handle<WeakCell> cell = Code::WeakCellFor(code);
14848 Handle<DependentCode> codes = DependentCode::InsertWeakCode( 14540 Handle<DependentCode> codes = DependentCode::InsertWeakCode(
14849 Handle<DependentCode>(map->dependent_code()), group, cell); 14541 Handle<DependentCode>(map->dependent_code()), group, cell);
14850 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); 14542 if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
14851 } 14543 }
14852 14544
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
15241 // Setting the prototype of an Array instance invalidates the species 14933 // Setting the prototype of an Array instance invalidates the species
15242 // protector 14934 // protector
15243 // because it could change the constructor property of the instance, which 14935 // because it could change the constructor property of the instance, which
15244 // could change the @@species constructor. 14936 // could change the @@species constructor.
15245 if (object->IsJSArray() && isolate->IsArraySpeciesLookupChainIntact()) { 14937 if (object->IsJSArray() && isolate->IsArraySpeciesLookupChainIntact()) {
15246 isolate->CountUsage( 14938 isolate->CountUsage(
15247 v8::Isolate::UseCounterFeature::kArrayInstanceProtoModified); 14939 v8::Isolate::UseCounterFeature::kArrayInstanceProtoModified);
15248 isolate->InvalidateArraySpeciesProtector(); 14940 isolate->InvalidateArraySpeciesProtector();
15249 } 14941 }
15250 14942
15251 const bool observed = from_javascript && object->map()->is_observed();
15252 Handle<Object> old_value;
15253 if (observed) {
15254 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, old_value,
15255 JSReceiver::GetPrototype(isolate, object),
15256 Nothing<bool>());
15257 }
15258
15259 Maybe<bool> result =
15260 SetPrototypeUnobserved(object, value, from_javascript, should_throw);
15261 MAYBE_RETURN(result, Nothing<bool>());
15262
15263 if (result.FromJust() && observed) {
15264 Handle<Object> new_value;
15265 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, new_value,
15266 JSReceiver::GetPrototype(isolate, object),
15267 Nothing<bool>());
15268 if (!new_value->SameValue(*old_value)) {
15269 RETURN_ON_EXCEPTION_VALUE(
15270 isolate, JSObject::EnqueueChangeRecord(
15271 object, "setPrototype",
15272 isolate->factory()->proto_string(), old_value),
15273 Nothing<bool>());
15274 }
15275 }
15276
15277 return result;
15278 }
15279
15280
15281 Maybe<bool> JSObject::SetPrototypeUnobserved(Handle<JSObject> object,
15282 Handle<Object> value,
15283 bool from_javascript,
15284 ShouldThrow should_throw) {
15285 #ifdef DEBUG 14943 #ifdef DEBUG
15286 int size = object->Size(); 14944 int size = object->Size();
15287 #endif 14945 #endif
15288 14946
15289 Isolate* isolate = object->GetIsolate();
15290
15291 if (from_javascript) { 14947 if (from_javascript) {
15292 if (object->IsAccessCheckNeeded() && 14948 if (object->IsAccessCheckNeeded() &&
15293 !isolate->MayAccess(handle(isolate->context()), object)) { 14949 !isolate->MayAccess(handle(isolate->context()), object)) {
15294 isolate->ReportFailedAccessCheck(object); 14950 isolate->ReportFailedAccessCheck(object);
15295 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); 14951 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
15296 RETURN_FAILURE(isolate, should_throw, 14952 RETURN_FAILURE(isolate, should_throw,
15297 NewTypeError(MessageTemplate::kNoAccess)); 14953 NewTypeError(MessageTemplate::kNoAccess));
15298 } 14954 }
15299 } else { 14955 } else {
15300 DCHECK(!object->IsAccessCheckNeeded()); 14956 DCHECK(!object->IsAccessCheckNeeded());
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
15516 Handle<Object> value, 15172 Handle<Object> value,
15517 PropertyAttributes attributes, 15173 PropertyAttributes attributes,
15518 ShouldThrow should_throw) { 15174 ShouldThrow should_throw) {
15519 DCHECK(object->map()->is_extensible()); 15175 DCHECK(object->map()->is_extensible());
15520 15176
15521 Isolate* isolate = object->GetIsolate(); 15177 Isolate* isolate = object->GetIsolate();
15522 15178
15523 uint32_t old_length = 0; 15179 uint32_t old_length = 0;
15524 uint32_t new_capacity = 0; 15180 uint32_t new_capacity = 0;
15525 15181
15526 Handle<Object> old_length_handle;
15527 if (object->IsJSArray()) { 15182 if (object->IsJSArray()) {
15528 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length)); 15183 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
15529 if (object->map()->is_observed()) {
15530 old_length_handle = handle(JSArray::cast(*object)->length(), isolate);
15531 }
15532 } 15184 }
15533 15185
15534 ElementsKind kind = object->GetElementsKind(); 15186 ElementsKind kind = object->GetElementsKind();
15535 FixedArrayBase* elements = object->elements(); 15187 FixedArrayBase* elements = object->elements();
15536 ElementsKind dictionary_kind = DICTIONARY_ELEMENTS; 15188 ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
15537 if (IsSloppyArgumentsElements(kind)) { 15189 if (IsSloppyArgumentsElements(kind)) {
15538 elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1)); 15190 elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
15539 dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS; 15191 dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
15540 } else if (IsStringWrapperElementsKind(kind)) { 15192 } else if (IsStringWrapperElementsKind(kind)) {
15541 dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS; 15193 dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
(...skipping 23 matching lines...) Expand all
15565 accessor->Add(object, index, value, attributes, new_capacity); 15217 accessor->Add(object, index, value, attributes, new_capacity);
15566 15218
15567 uint32_t new_length = old_length; 15219 uint32_t new_length = old_length;
15568 Handle<Object> new_length_handle; 15220 Handle<Object> new_length_handle;
15569 if (object->IsJSArray() && index >= old_length) { 15221 if (object->IsJSArray() && index >= old_length) {
15570 new_length = index + 1; 15222 new_length = index + 1;
15571 new_length_handle = isolate->factory()->NewNumberFromUint(new_length); 15223 new_length_handle = isolate->factory()->NewNumberFromUint(new_length);
15572 JSArray::cast(*object)->set_length(*new_length_handle); 15224 JSArray::cast(*object)->set_length(*new_length_handle);
15573 } 15225 }
15574 15226
15575 if (!old_length_handle.is_null() && new_length != old_length) {
15576 // |old_length_handle| is kept null above unless the object is observed.
15577 DCHECK(object->map()->is_observed());
15578 Handle<JSArray> array = Handle<JSArray>::cast(object);
15579 Handle<String> name = isolate->factory()->Uint32ToString(index);
15580
15581 RETURN_ON_EXCEPTION_VALUE(isolate, BeginPerformSplice(array),
15582 Nothing<bool>());
15583 RETURN_ON_EXCEPTION_VALUE(
15584 isolate, EnqueueChangeRecord(array, "add", name,
15585 isolate->factory()->the_hole_value()),
15586 Nothing<bool>());
15587 RETURN_ON_EXCEPTION_VALUE(
15588 isolate, EnqueueChangeRecord(array, "update",
15589 isolate->factory()->length_string(),
15590 old_length_handle),
15591 Nothing<bool>());
15592 RETURN_ON_EXCEPTION_VALUE(isolate, EndPerformSplice(array),
15593 Nothing<bool>());
15594 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
15595 RETURN_ON_EXCEPTION_VALUE(isolate,
15596 EnqueueSpliceRecord(array, old_length, deleted,
15597 new_length - old_length),
15598 Nothing<bool>());
15599 } else if (object->map()->is_observed()) {
15600 Handle<String> name = isolate->factory()->Uint32ToString(index);
15601 RETURN_ON_EXCEPTION_VALUE(
15602 isolate, EnqueueChangeRecord(object, "add", name,
15603 isolate->factory()->the_hole_value()),
15604 Nothing<bool>());
15605 }
15606
15607 return Just(true); 15227 return Just(true);
15608 } 15228 }
15609 15229
15610 15230
15611 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) { 15231 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
15612 if (!HasFastElements()) return false; 15232 if (!HasFastElements()) return false;
15613 uint32_t capacity = static_cast<uint32_t>(elements()->length()); 15233 uint32_t capacity = static_cast<uint32_t>(elements()->length());
15614 uint32_t new_capacity; 15234 uint32_t new_capacity;
15615 return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) && 15235 return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
15616 ShouldConvertToSlowElements(this, capacity, new_length - 1, 15236 ShouldConvertToSlowElements(this, capacity, new_length - 1,
(...skipping 1630 matching lines...) Expand 10 before | Expand all | Expand 10 after
17247 } 16867 }
17248 16868
17249 16869
17250 // Collects all defined (non-hole) and non-undefined (array) elements at 16870 // Collects all defined (non-hole) and non-undefined (array) elements at
17251 // the start of the elements array. 16871 // the start of the elements array.
17252 // If the object is in dictionary mode, it is converted to fast elements 16872 // If the object is in dictionary mode, it is converted to fast elements
17253 // mode. 16873 // mode.
17254 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object, 16874 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
17255 uint32_t limit) { 16875 uint32_t limit) {
17256 Isolate* isolate = object->GetIsolate(); 16876 Isolate* isolate = object->GetIsolate();
17257 if (object->HasSloppyArgumentsElements() || 16877 if (object->HasSloppyArgumentsElements()) {
17258 object->map()->is_observed()) {
17259 return handle(Smi::FromInt(-1), isolate); 16878 return handle(Smi::FromInt(-1), isolate);
17260 } 16879 }
17261 16880
17262 if (object->HasStringWrapperElements()) { 16881 if (object->HasStringWrapperElements()) {
17263 int len = String::cast(Handle<JSValue>::cast(object)->value())->length(); 16882 int len = String::cast(Handle<JSValue>::cast(object)->value())->length();
17264 return handle(Smi::FromInt(len), isolate); 16883 return handle(Smi::FromInt(len), isolate);
17265 } 16884 }
17266 16885
17267 if (object->HasDictionaryElements()) { 16886 if (object->HasDictionaryElements()) {
17268 // Convert to fast elements containing only the existing properties. 16887 // Convert to fast elements containing only the existing properties.
(...skipping 2166 matching lines...) Expand 10 before | Expand all | Expand 10 after
19435 if (cell->value() != *new_value) { 19054 if (cell->value() != *new_value) {
19436 cell->set_value(*new_value); 19055 cell->set_value(*new_value);
19437 Isolate* isolate = cell->GetIsolate(); 19056 Isolate* isolate = cell->GetIsolate();
19438 cell->dependent_code()->DeoptimizeDependentCodeGroup( 19057 cell->dependent_code()->DeoptimizeDependentCodeGroup(
19439 isolate, DependentCode::kPropertyCellChangedGroup); 19058 isolate, DependentCode::kPropertyCellChangedGroup);
19440 } 19059 }
19441 } 19060 }
19442 19061
19443 } // namespace internal 19062 } // namespace internal
19444 } // namespace v8 19063 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698