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
3// found in the LICENSE file.
4
5#include "src/objects.h"
6
7#include <algorithm>
8#include <cmath>
9#include <memory>
10#include <sstream>
11#include <vector>
12
13#include "src/objects-inl.h"
14
15#include "src/accessors.h"
16#include "src/allocation-site-scopes.h"
17#include "src/api-arguments-inl.h"
18#include "src/api-natives.h"
19#include "src/api.h"
20#include "src/arguments.h"
21#include "src/ast/ast.h"
22#include "src/ast/scopes.h"
23#include "src/base/bits.h"
24#include "src/base/overflowing-math.h"
25#include "src/base/utils/random-number-generator.h"
26#include "src/bootstrapper.h"
27#include "src/builtins/builtins.h"
28#include "src/compiler.h"
29#include "src/counters-inl.h"
30#include "src/counters.h"
31#include "src/date.h"
32#include "src/debug/debug.h"
33#include "src/elements.h"
34#include "src/execution.h"
35#include "src/field-index-inl.h"
36#include "src/field-index.h"
37#include "src/field-type.h"
38#include "src/frames-inl.h"
39#include "src/function-kind.h"
40#include "src/globals.h"
41#include "src/heap/heap-inl.h"
42#include "src/heap/read-only-heap.h"
43#include "src/ic/ic.h"
44#include "src/identity-map.h"
45#include "src/isolate-inl.h"
46#include "src/keys.h"
47#include "src/log.h"
48#include "src/lookup-inl.h"
49#include "src/map-updater.h"
50#include "src/message-template.h"
51#include "src/microtask-queue.h"
52#include "src/objects-body-descriptors-inl.h"
53#include "src/objects/allocation-site-inl.h"
54#include "src/objects/api-callbacks.h"
55#include "src/objects/arguments-inl.h"
56#include "src/objects/bigint.h"
57#include "src/objects/cell-inl.h"
58#include "src/objects/code-inl.h"
59#include "src/objects/compilation-cache-inl.h"
60#include "src/objects/debug-objects-inl.h"
61#include "src/objects/embedder-data-array-inl.h"
62#include "src/objects/foreign.h"
63#include "src/objects/frame-array-inl.h"
64#include "src/objects/free-space-inl.h"
65#include "src/objects/hash-table-inl.h"
66#include "src/objects/js-array-inl.h"
67#ifdef V8_INTL_SUPPORT
68#include "src/objects/js-break-iterator.h"
69#include "src/objects/js-collator.h"
70#endif // V8_INTL_SUPPORT
71#include "src/objects/js-collection-inl.h"
72#ifdef V8_INTL_SUPPORT
73#include "src/objects/js-date-time-format.h"
74#endif // V8_INTL_SUPPORT
75#include "src/objects/js-generator-inl.h"
76#ifdef V8_INTL_SUPPORT
77#include "src/objects/js-list-format.h"
78#include "src/objects/js-locale.h"
79#include "src/objects/js-number-format.h"
80#include "src/objects/js-plural-rules.h"
81#endif // V8_INTL_SUPPORT
82#include "src/objects/js-regexp-inl.h"
83#include "src/objects/js-regexp-string-iterator.h"
84#ifdef V8_INTL_SUPPORT
85#include "src/objects/js-relative-time-format.h"
86#include "src/objects/js-segment-iterator.h"
87#include "src/objects/js-segmenter.h"
88#endif // V8_INTL_SUPPORT
89#include "src/objects/js-weak-refs-inl.h"
90#include "src/objects/literal-objects-inl.h"
91#include "src/objects/map-inl.h"
92#include "src/objects/map.h"
93#include "src/objects/microtask-inl.h"
94#include "src/objects/module-inl.h"
95#include "src/objects/promise-inl.h"
96#include "src/objects/slots-atomic-inl.h"
97#include "src/objects/stack-frame-info-inl.h"
98#include "src/objects/string-comparator.h"
99#include "src/objects/struct-inl.h"
100#include "src/ostreams.h"
101#include "src/parsing/preparse-data.h"
102#include "src/property-descriptor.h"
103#include "src/prototype.h"
104#include "src/regexp/jsregexp.h"
105#include "src/source-position-table.h"
106#include "src/string-builder-inl.h"
107#include "src/string-search.h"
108#include "src/string-stream.h"
109#include "src/transitions-inl.h"
110#include "src/unicode-decoder.h"
111#include "src/unicode-inl.h"
112#include "src/utils-inl.h"
113#include "src/wasm/wasm-engine.h"
114#include "src/wasm/wasm-objects.h"
115#include "src/zone/zone.h"
116
117namespace v8 {
118namespace internal {
119
120ShouldThrow GetShouldThrow(Isolate* isolate, Maybe<ShouldThrow> should_throw) {
121 if (should_throw.IsJust()) return should_throw.FromJust();
122
123 LanguageMode mode = isolate->context()->scope_info()->language_mode();
124 if (mode == LanguageMode::kStrict) return kThrowOnError;
125
126 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
127 if (!(it.frame()->is_optimized() || it.frame()->is_interpreted())) {
128 continue;
129 }
130 // Get the language mode from closure.
131 JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(it.frame());
132 std::vector<SharedFunctionInfo> functions;
133 js_frame->GetFunctions(&functions);
134 LanguageMode closure_language_mode = functions.back()->language_mode();
135 if (closure_language_mode > mode) {
136 mode = closure_language_mode;
137 }
138 break;
139 }
140
141 return is_sloppy(mode) ? kDontThrow : kThrowOnError;
142}
143
144bool ComparisonResultToBool(Operation op, ComparisonResult result) {
145 switch (op) {
146 case Operation::kLessThan:
147 return result == ComparisonResult::kLessThan;
148 case Operation::kLessThanOrEqual:
149 return result == ComparisonResult::kLessThan ||
150 result == ComparisonResult::kEqual;
151 case Operation::kGreaterThan:
152 return result == ComparisonResult::kGreaterThan;
153 case Operation::kGreaterThanOrEqual:
154 return result == ComparisonResult::kGreaterThan ||
155 result == ComparisonResult::kEqual;
156 default:
157 break;
158 }
159 UNREACHABLE();
160}
161
162std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
163 switch (instance_type) {
164#define WRITE_TYPE(TYPE) \
165 case TYPE: \
166 return os << #TYPE;
167 INSTANCE_TYPE_LIST(WRITE_TYPE)
168#undef WRITE_TYPE
169 }
170 UNREACHABLE();
171}
172
173Handle<FieldType> Object::OptimalType(Isolate* isolate,
174 Representation representation) {
175 if (representation.IsNone()) return FieldType::None(isolate);
176 if (FLAG_track_field_types) {
177 if (representation.IsHeapObject() && IsHeapObject()) {
178 // We can track only JavaScript objects with stable maps.
179 Handle<Map> map(HeapObject::cast(*this)->map(), isolate);
180 if (map->is_stable() && map->IsJSReceiverMap()) {
181 return FieldType::Class(map, isolate);
182 }
183 }
184 }
185 return FieldType::Any(isolate);
186}
187
188Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object,
189 Representation representation) {
190 if (!representation.IsDouble()) return object;
191 auto result = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
192 if (object->IsUninitialized(isolate)) {
193 result->set_value_as_bits(kHoleNanInt64);
194 } else if (object->IsMutableHeapNumber()) {
195 // Ensure that all bits of the double value are preserved.
196 result->set_value_as_bits(
197 MutableHeapNumber::cast(*object)->value_as_bits());
198 } else {
199 result->set_value(object->Number());
200 }
201 return result;
202}
203
204Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object,
205 Representation representation) {
206 DCHECK(!object->IsUninitialized(isolate));
207 if (!representation.IsDouble()) {
208 DCHECK(object->FitsRepresentation(representation));
209 return object;
210 }
211 return isolate->factory()->NewHeapNumber(
212 MutableHeapNumber::cast(*object)->value());
213}
214
215MaybeHandle<JSReceiver> Object::ToObjectImpl(Isolate* isolate,
216 Handle<Object> object,
217 const char* method_name) {
218 DCHECK(!object->IsJSReceiver()); // Use ToObject() for fast path.
219 Handle<Context> native_context = isolate->native_context();
220 Handle<JSFunction> constructor;
221 if (object->IsSmi()) {
222 constructor = handle(native_context->number_function(), isolate);
223 } else {
224 int constructor_function_index =
225 Handle<HeapObject>::cast(object)->map()->GetConstructorFunctionIndex();
226 if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
227 if (method_name != nullptr) {
228 THROW_NEW_ERROR(
229 isolate,
230 NewTypeError(
231 MessageTemplate::kCalledOnNullOrUndefined,
232 isolate->factory()->NewStringFromAsciiChecked(method_name)),
233 JSReceiver);
234 }
235 THROW_NEW_ERROR(isolate,
236 NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
237 JSReceiver);
238 }
239 constructor = handle(
240 JSFunction::cast(native_context->get(constructor_function_index)),
241 isolate);
242 }
243 Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
244 Handle<JSValue>::cast(result)->set_value(*object);
245 return result;
246}
247
248// ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
249// static
250MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
251 Handle<Object> object) {
252 if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
253 if (object->IsNullOrUndefined(isolate)) {
254 return isolate->global_proxy();
255 }
256 return Object::ToObject(isolate, object);
257}
258
259// static
260MaybeHandle<Object> Object::ConvertToNumberOrNumeric(Isolate* isolate,
261 Handle<Object> input,
262 Conversion mode) {
263 while (true) {
264 if (input->IsNumber()) {
265 return input;
266 }
267 if (input->IsString()) {
268 return String::ToNumber(isolate, Handle<String>::cast(input));
269 }
270 if (input->IsOddball()) {
271 return Oddball::ToNumber(isolate, Handle<Oddball>::cast(input));
272 }
273 if (input->IsSymbol()) {
274 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
275 Object);
276 }
277 if (input->IsBigInt()) {
278 if (mode == Conversion::kToNumeric) return input;
279 DCHECK_EQ(mode, Conversion::kToNumber);
280 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kBigIntToNumber),
281 Object);
282 }
283 ASSIGN_RETURN_ON_EXCEPTION(
284 isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
285 ToPrimitiveHint::kNumber),
286 Object);
287 }
288}
289
290// static
291MaybeHandle<Object> Object::ConvertToInteger(Isolate* isolate,
292 Handle<Object> input) {
293 ASSIGN_RETURN_ON_EXCEPTION(
294 isolate, input,
295 ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
296 if (input->IsSmi()) return input;
297 return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
298}
299
300// static
301MaybeHandle<Object> Object::ConvertToInt32(Isolate* isolate,
302 Handle<Object> input) {
303 ASSIGN_RETURN_ON_EXCEPTION(
304 isolate, input,
305 ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
306 if (input->IsSmi()) return input;
307 return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
308}
309
310// static
311MaybeHandle<Object> Object::ConvertToUint32(Isolate* isolate,
312 Handle<Object> input) {
313 ASSIGN_RETURN_ON_EXCEPTION(
314 isolate, input,
315 ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
316 if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
317 return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
318}
319
320// static
321MaybeHandle<Name> Object::ConvertToName(Isolate* isolate,
322 Handle<Object> input) {
323 ASSIGN_RETURN_ON_EXCEPTION(
324 isolate, input, Object::ToPrimitive(input, ToPrimitiveHint::kString),
325 Name);
326 if (input->IsName()) return Handle<Name>::cast(input);
327 return ToString(isolate, input);
328}
329
330// ES6 7.1.14
331// static
332MaybeHandle<Object> Object::ConvertToPropertyKey(Isolate* isolate,
333 Handle<Object> value) {
334 // 1. Let key be ToPrimitive(argument, hint String).
335 MaybeHandle<Object> maybe_key =
336 Object::ToPrimitive(value, ToPrimitiveHint::kString);
337 // 2. ReturnIfAbrupt(key).
338 Handle<Object> key;
339 if (!maybe_key.ToHandle(&key)) return key;
340 // 3. If Type(key) is Symbol, then return key.
341 if (key->IsSymbol()) return key;
342 // 4. Return ToString(key).
343 // Extending spec'ed behavior, we'd be happy to return an element index.
344 if (key->IsSmi()) return key;
345 if (key->IsHeapNumber()) {
346 uint32_t uint_value;
347 if (value->ToArrayLength(&uint_value) &&
348 uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) {
349 return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate);
350 }
351 }
352 return Object::ToString(isolate, key);
353}
354
355// static
356MaybeHandle<String> Object::ConvertToString(Isolate* isolate,
357 Handle<Object> input) {
358 while (true) {
359 if (input->IsOddball()) {
360 return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
361 }
362 if (input->IsNumber()) {
363 return isolate->factory()->NumberToString(input);
364 }
365 if (input->IsSymbol()) {
366 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
367 String);
368 }
369 if (input->IsBigInt()) {
370 return BigInt::ToString(isolate, Handle<BigInt>::cast(input));
371 }
372 ASSIGN_RETURN_ON_EXCEPTION(
373 isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
374 ToPrimitiveHint::kString),
375 String);
376 // The previous isString() check happened in Object::ToString and thus we
377 // put it at the end of the loop in this helper.
378 if (input->IsString()) {
379 return Handle<String>::cast(input);
380 }
381 }
382}
383
384namespace {
385
386bool IsErrorObject(Isolate* isolate, Handle<Object> object) {
387 if (!object->IsJSReceiver()) return false;
388 Handle<Symbol> symbol = isolate->factory()->stack_trace_symbol();
389 return JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(object), symbol)
390 .FromMaybe(false);
391}
392
393Handle<String> AsStringOrEmpty(Isolate* isolate, Handle<Object> object) {
394 return object->IsString() ? Handle<String>::cast(object)
395 : isolate->factory()->empty_string();
396}
397
398Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
399 Handle<Object> input) {
400 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
401
402 Handle<Name> name_key = isolate->factory()->name_string();
403 Handle<Object> name = JSReceiver::GetDataProperty(receiver, name_key);
404 Handle<String> name_str = AsStringOrEmpty(isolate, name);
405
406 Handle<Name> msg_key = isolate->factory()->message_string();
407 Handle<Object> msg = JSReceiver::GetDataProperty(receiver, msg_key);
408 Handle<String> msg_str = AsStringOrEmpty(isolate, msg);
409
410 if (name_str->length() == 0) return msg_str;
411 if (msg_str->length() == 0) return name_str;
412
413 IncrementalStringBuilder builder(isolate);
414 builder.AppendString(name_str);
415 builder.AppendCString(": ");
416 builder.AppendString(msg_str);
417
418 return builder.Finish().ToHandleChecked();
419}
420
421} // namespace
422
423// static
424Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
425 Handle<Object> input) {
426 DisallowJavascriptExecution no_js(isolate);
427
428 if (input->IsString() || input->IsNumber() || input->IsOddball()) {
429 return Object::ToString(isolate, input).ToHandleChecked();
430 } else if (input->IsBigInt()) {
431 MaybeHandle<String> maybe_string =
432 BigInt::ToString(isolate, Handle<BigInt>::cast(input), 10, kDontThrow);
433 Handle<String> result;
434 if (maybe_string.ToHandle(&result)) return result;
435 // BigInt-to-String conversion can fail on 32-bit platforms where
436 // String::kMaxLength is too small to fit this BigInt.
437 return isolate->factory()->NewStringFromStaticChars(
438 "<a very large BigInt>");
439 } else if (input->IsFunction()) {
440 // -- F u n c t i o n
441 Handle<String> fun_str;
442 if (input->IsJSBoundFunction()) {
443 fun_str = JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(input));
444 } else {
445 DCHECK(input->IsJSFunction());
446 fun_str = JSFunction::ToString(Handle<JSFunction>::cast(input));
447 }
448
449 if (fun_str->length() > 128) {
450 IncrementalStringBuilder builder(isolate);
451 builder.AppendString(isolate->factory()->NewSubString(fun_str, 0, 111));
452 builder.AppendCString("...<omitted>...");
453 builder.AppendString(isolate->factory()->NewSubString(
454 fun_str, fun_str->length() - 2, fun_str->length()));
455
456 return builder.Finish().ToHandleChecked();
457 }
458 return fun_str;
459 } else if (input->IsSymbol()) {
460 // -- S y m b o l
461 Handle<Symbol> symbol = Handle<Symbol>::cast(input);
462
463 if (symbol->is_private_name()) {
464 return Handle<String>(String::cast(symbol->name()), isolate);
465 }
466
467 IncrementalStringBuilder builder(isolate);
468 builder.AppendCString("Symbol(");
469 if (symbol->name()->IsString()) {
470 builder.AppendString(handle(String::cast(symbol->name()), isolate));
471 }
472 builder.AppendCharacter(')');
473
474 return builder.Finish().ToHandleChecked();
475 } else if (input->IsJSReceiver()) {
476 // -- J S R e c e i v e r
477 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
478 Handle<Object> to_string = JSReceiver::GetDataProperty(
479 receiver, isolate->factory()->toString_string());
480
481 if (IsErrorObject(isolate, input) ||
482 *to_string == *isolate->error_to_string()) {
483 // When internally formatting error objects, use a side-effects-free
484 // version of Error.prototype.toString independent of the actually
485 // installed toString method.
486 return NoSideEffectsErrorToString(isolate, input);
487 } else if (*to_string == *isolate->object_to_string()) {
488 Handle<Object> ctor = JSReceiver::GetDataProperty(
489 receiver, isolate->factory()->constructor_string());
490 if (ctor->IsFunction()) {
491 Handle<String> ctor_name;
492 if (ctor->IsJSBoundFunction()) {
493 ctor_name = JSBoundFunction::GetName(
494 isolate, Handle<JSBoundFunction>::cast(ctor))
495 .ToHandleChecked();
496 } else if (ctor->IsJSFunction()) {
497 Handle<Object> ctor_name_obj =
498 JSFunction::GetName(isolate, Handle<JSFunction>::cast(ctor));
499 ctor_name = AsStringOrEmpty(isolate, ctor_name_obj);
500 }
501
502 if (ctor_name->length() != 0) {
503 IncrementalStringBuilder builder(isolate);
504 builder.AppendCString("#<");
505 builder.AppendString(ctor_name);
506 builder.AppendCString(">");
507
508 return builder.Finish().ToHandleChecked();
509 }
510 }
511 }
512 }
513
514 // At this point, input is either none of the above or a JSReceiver.
515
516 Handle<JSReceiver> receiver;
517 if (input->IsJSReceiver()) {
518 receiver = Handle<JSReceiver>::cast(input);
519 } else {
520 // This is the only case where Object::ToObject throws.
521 DCHECK(!input->IsSmi());
522 int constructor_function_index =
523 Handle<HeapObject>::cast(input)->map()->GetConstructorFunctionIndex();
524 if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
525 return isolate->factory()->NewStringFromAsciiChecked("[object Unknown]");
526 }
527
528 receiver = Object::ToObjectImpl(isolate, input).ToHandleChecked();
529 }
530
531 Handle<String> builtin_tag = handle(receiver->class_name(), isolate);
532 Handle<Object> tag_obj = JSReceiver::GetDataProperty(
533 receiver, isolate->factory()->to_string_tag_symbol());
534 Handle<String> tag =
535 tag_obj->IsString() ? Handle<String>::cast(tag_obj) : builtin_tag;
536
537 IncrementalStringBuilder builder(isolate);
538 builder.AppendCString("[object ");
539 builder.AppendString(tag);
540 builder.AppendCString("]");
541
542 return builder.Finish().ToHandleChecked();
543}
544
545// static
546MaybeHandle<Object> Object::ConvertToLength(Isolate* isolate,
547 Handle<Object> input) {
548 ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
549 if (input->IsSmi()) {
550 int value = std::max(Smi::ToInt(*input), 0);
551 return handle(Smi::FromInt(value), isolate);
552 }
553 double len = DoubleToInteger(input->Number());
554 if (len <= 0.0) {
555 return handle(Smi::kZero, isolate);
556 } else if (len >= kMaxSafeInteger) {
557 len = kMaxSafeInteger;
558 }
559 return isolate->factory()->NewNumber(len);
560}
561
562// static
563MaybeHandle<Object> Object::ConvertToIndex(Isolate* isolate,
564 Handle<Object> input,
565 MessageTemplate error_index) {
566 if (input->IsUndefined(isolate)) return handle(Smi::kZero, isolate);
567 ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
568 if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
569 double len = DoubleToInteger(input->Number()) + 0.0;
570 auto js_len = isolate->factory()->NewNumber(len);
571 if (len < 0.0 || len > kMaxSafeInteger) {
572 THROW_NEW_ERROR(isolate, NewRangeError(error_index, js_len), Object);
573 }
574 return js_len;
575}
576
577bool Object::BooleanValue(Isolate* isolate) {
578 if (IsSmi()) return Smi::ToInt(*this) != 0;
579 DCHECK(IsHeapObject());
580 if (IsBoolean()) return IsTrue(isolate);
581 if (IsNullOrUndefined(isolate)) return false;
582 if (IsUndetectable()) return false; // Undetectable object is false.
583 if (IsString()) return String::cast(*this)->length() != 0;
584 if (IsHeapNumber()) return DoubleToBoolean(HeapNumber::cast(*this)->value());
585 if (IsBigInt()) return BigInt::cast(*this)->ToBoolean();
586 return true;
587}
588
589Object Object::ToBoolean(Isolate* isolate) {
590 if (IsBoolean()) return *this;
591 return isolate->heap()->ToBoolean(BooleanValue(isolate));
592}
593
594namespace {
595
596// TODO(bmeurer): Maybe we should introduce a marker interface Number,
597// where we put all these methods at some point?
598ComparisonResult StrictNumberCompare(double x, double y) {
599 if (std::isnan(x) || std::isnan(y)) {
600 return ComparisonResult::kUndefined;
601 } else if (x < y) {
602 return ComparisonResult::kLessThan;
603 } else if (x > y) {
604 return ComparisonResult::kGreaterThan;
605 } else {
606 return ComparisonResult::kEqual;
607 }
608}
609
610// See Number case of ES6#sec-strict-equality-comparison
611// Returns false if x or y is NaN, treats -0.0 as equal to 0.0.
612bool StrictNumberEquals(double x, double y) {
613 // Must check explicitly for NaN's on Windows, but -0 works fine.
614 if (std::isnan(x) || std::isnan(y)) return false;
615 return x == y;
616}
617
618bool StrictNumberEquals(const Object x, const Object y) {
619 return StrictNumberEquals(x->Number(), y->Number());
620}
621
622bool StrictNumberEquals(Handle<Object> x, Handle<Object> y) {
623 return StrictNumberEquals(*x, *y);
624}
625
626ComparisonResult Reverse(ComparisonResult result) {
627 if (result == ComparisonResult::kLessThan) {
628 return ComparisonResult::kGreaterThan;
629 }
630 if (result == ComparisonResult::kGreaterThan) {
631 return ComparisonResult::kLessThan;
632 }
633 return result;
634}
635
636} // anonymous namespace
637
638// static
639Maybe<ComparisonResult> Object::Compare(Isolate* isolate, Handle<Object> x,
640 Handle<Object> y) {
641 // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
642 if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
643 !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
644 return Nothing<ComparisonResult>();
645 }
646 if (x->IsString() && y->IsString()) {
647 // ES6 section 7.2.11 Abstract Relational Comparison step 5.
648 return Just(String::Compare(isolate, Handle<String>::cast(x),
649 Handle<String>::cast(y)));
650 }
651 if (x->IsBigInt() && y->IsString()) {
652 return Just(BigInt::CompareToString(isolate, Handle<BigInt>::cast(x),
653 Handle<String>::cast(y)));
654 }
655 if (x->IsString() && y->IsBigInt()) {
656 return Just(Reverse(BigInt::CompareToString(
657 isolate, Handle<BigInt>::cast(y), Handle<String>::cast(x))));
658 }
659 // ES6 section 7.2.11 Abstract Relational Comparison step 6.
660 if (!Object::ToNumeric(isolate, x).ToHandle(&x) ||
661 !Object::ToNumeric(isolate, y).ToHandle(&y)) {
662 return Nothing<ComparisonResult>();
663 }
664
665 bool x_is_number = x->IsNumber();
666 bool y_is_number = y->IsNumber();
667 if (x_is_number && y_is_number) {
668 return Just(StrictNumberCompare(x->Number(), y->Number()));
669 } else if (!x_is_number && !y_is_number) {
670 return Just(BigInt::CompareToBigInt(Handle<BigInt>::cast(x),
671 Handle<BigInt>::cast(y)));
672 } else if (x_is_number) {
673 return Just(Reverse(BigInt::CompareToNumber(Handle<BigInt>::cast(y), x)));
674 } else {
675 return Just(BigInt::CompareToNumber(Handle<BigInt>::cast(x), y));
676 }
677}
678
679
680// static
681Maybe<bool> Object::Equals(Isolate* isolate, Handle<Object> x,
682 Handle<Object> y) {
683 // This is the generic version of Abstract Equality Comparison. Must be in
684 // sync with CodeStubAssembler::Equal.
685 while (true) {
686 if (x->IsNumber()) {
687 if (y->IsNumber()) {
688 return Just(StrictNumberEquals(x, y));
689 } else if (y->IsBoolean()) {
690 return Just(
691 StrictNumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
692 } else if (y->IsString()) {
693 return Just(StrictNumberEquals(
694 x, String::ToNumber(isolate, Handle<String>::cast(y))));
695 } else if (y->IsBigInt()) {
696 return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
697 } else if (y->IsJSReceiver()) {
698 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
699 .ToHandle(&y)) {
700 return Nothing<bool>();
701 }
702 } else {
703 return Just(false);
704 }
705 } else if (x->IsString()) {
706 if (y->IsString()) {
707 return Just(String::Equals(isolate, Handle<String>::cast(x),
708 Handle<String>::cast(y)));
709 } else if (y->IsNumber()) {
710 x = String::ToNumber(isolate, Handle<String>::cast(x));
711 return Just(StrictNumberEquals(x, y));
712 } else if (y->IsBoolean()) {
713 x = String::ToNumber(isolate, Handle<String>::cast(x));
714 return Just(
715 StrictNumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
716 } else if (y->IsBigInt()) {
717 return Just(BigInt::EqualToString(isolate, Handle<BigInt>::cast(y),
718 Handle<String>::cast(x)));
719 } else if (y->IsJSReceiver()) {
720 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
721 .ToHandle(&y)) {
722 return Nothing<bool>();
723 }
724 } else {
725 return Just(false);
726 }
727 } else if (x->IsBoolean()) {
728 if (y->IsOddball()) {
729 return Just(x.is_identical_to(y));
730 } else if (y->IsNumber()) {
731 return Just(
732 StrictNumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
733 } else if (y->IsString()) {
734 y = String::ToNumber(isolate, Handle<String>::cast(y));
735 return Just(
736 StrictNumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
737 } else if (y->IsBigInt()) {
738 x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
739 return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
740 } else if (y->IsJSReceiver()) {
741 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
742 .ToHandle(&y)) {
743 return Nothing<bool>();
744 }
745 x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
746 } else {
747 return Just(false);
748 }
749 } else if (x->IsSymbol()) {
750 if (y->IsSymbol()) {
751 return Just(x.is_identical_to(y));
752 } else if (y->IsJSReceiver()) {
753 if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
754 .ToHandle(&y)) {
755 return Nothing<bool>();
756 }
757 } else {
758 return Just(false);
759 }
760 } else if (x->IsBigInt()) {
761 if (y->IsBigInt()) {
762 return Just(BigInt::EqualToBigInt(BigInt::cast(*x), BigInt::cast(*y)));
763 }
764 return Equals(isolate, y, x);
765 } else if (x->IsJSReceiver()) {
766 if (y->IsJSReceiver()) {
767 return Just(x.is_identical_to(y));
768 } else if (y->IsUndetectable()) {
769 return Just(x->IsUndetectable());
770 } else if (y->IsBoolean()) {
771 y = Oddball::ToNumber(isolate, Handle<Oddball>::cast(y));
772 } else if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x))
773 .ToHandle(&x)) {
774 return Nothing<bool>();
775 }
776 } else {
777 return Just(x->IsUndetectable() && y->IsUndetectable());
778 }
779 }
780}
781
782bool Object::StrictEquals(Object that) {
783 if (this->IsNumber()) {
784 if (!that->IsNumber()) return false;
785 return StrictNumberEquals(*this, that);
786 } else if (this->IsString()) {
787 if (!that->IsString()) return false;
788 return String::cast(*this)->Equals(String::cast(that));
789 } else if (this->IsBigInt()) {
790 if (!that->IsBigInt()) return false;
791 return BigInt::EqualToBigInt(BigInt::cast(*this), BigInt::cast(that));
792 }
793 return *this == that;
794}
795
796// static
797Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
798 if (object->IsNumber()) return isolate->factory()->number_string();
799 if (object->IsOddball())
800 return handle(Oddball::cast(*object)->type_of(), isolate);
801 if (object->IsUndetectable()) {
802 return isolate->factory()->undefined_string();
803 }
804 if (object->IsString()) return isolate->factory()->string_string();
805 if (object->IsSymbol()) return isolate->factory()->symbol_string();
806 if (object->IsBigInt()) return isolate->factory()->bigint_string();
807 if (object->IsCallable()) return isolate->factory()->function_string();
808 return isolate->factory()->object_string();
809}
810
811
812// static
813MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
814 Handle<Object> rhs) {
815 if (lhs->IsNumber() && rhs->IsNumber()) {
816 return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
817 } else if (lhs->IsString() && rhs->IsString()) {
818 return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
819 Handle<String>::cast(rhs));
820 }
821 ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
822 ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
823 if (lhs->IsString() || rhs->IsString()) {
824 ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
825 Object);
826 ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
827 Object);
828 return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
829 Handle<String>::cast(rhs));
830 }
831 ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(isolate, rhs),
832 Object);
833 ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(isolate, lhs),
834 Object);
835 return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
836}
837
838
839// static
840MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
841 Handle<Object> callable,
842 Handle<Object> object) {
843 // The {callable} must have a [[Call]] internal method.
844 if (!callable->IsCallable()) return isolate->factory()->false_value();
845
846 // Check if {callable} is a bound function, and if so retrieve its
847 // [[BoundTargetFunction]] and use that instead of {callable}.
848 if (callable->IsJSBoundFunction()) {
849 Handle<Object> bound_callable(
850 Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
851 isolate);
852 return Object::InstanceOf(isolate, object, bound_callable);
853 }
854
855 // If {object} is not a receiver, return false.
856 if (!object->IsJSReceiver()) return isolate->factory()->false_value();
857
858 // Get the "prototype" of {callable}; raise an error if it's not a receiver.
859 Handle<Object> prototype;
860 ASSIGN_RETURN_ON_EXCEPTION(
861 isolate, prototype,
862 Object::GetProperty(isolate, callable,
863 isolate->factory()->prototype_string()),
864 Object);
865 if (!prototype->IsJSReceiver()) {
866 THROW_NEW_ERROR(
867 isolate,
868 NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
869 Object);
870 }
871
872 // Return whether or not {prototype} is in the prototype chain of {object}.
873 Maybe<bool> result = JSReceiver::HasInPrototypeChain(
874 isolate, Handle<JSReceiver>::cast(object), prototype);
875 if (result.IsNothing()) return MaybeHandle<Object>();
876 return isolate->factory()->ToBoolean(result.FromJust());
877}
878
879// static
880MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object> object,
881 Handle<Object> callable) {
882 // The {callable} must be a receiver.
883 if (!callable->IsJSReceiver()) {
884 THROW_NEW_ERROR(isolate,
885 NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
886 Object);
887 }
888
889 // Lookup the @@hasInstance method on {callable}.
890 Handle<Object> inst_of_handler;
891 ASSIGN_RETURN_ON_EXCEPTION(
892 isolate, inst_of_handler,
893 Object::GetMethod(Handle<JSReceiver>::cast(callable),
894 isolate->factory()->has_instance_symbol()),
895 Object);
896 if (!inst_of_handler->IsUndefined(isolate)) {
897 // Call the {inst_of_handler} on the {callable}.
898 Handle<Object> result;
899 ASSIGN_RETURN_ON_EXCEPTION(
900 isolate, result,
901 Execution::Call(isolate, inst_of_handler, callable, 1, &object),
902 Object);
903 return isolate->factory()->ToBoolean(result->BooleanValue(isolate));
904 }
905
906 // The {callable} must have a [[Call]] internal method.
907 if (!callable->IsCallable()) {
908 THROW_NEW_ERROR(
909 isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
910 Object);
911 }
912
913 // Fall back to OrdinaryHasInstance with {callable} and {object}.
914 Handle<Object> result;
915 ASSIGN_RETURN_ON_EXCEPTION(
916 isolate, result, Object::OrdinaryHasInstance(isolate, callable, object),
917 Object);
918 return result;
919}
920
921// static
922MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
923 Handle<Name> name) {
924 Handle<Object> func;
925 Isolate* isolate = receiver->GetIsolate();
926 ASSIGN_RETURN_ON_EXCEPTION(
927 isolate, func, JSReceiver::GetProperty(isolate, receiver, name), Object);
928 if (func->IsNullOrUndefined(isolate)) {
929 return isolate->factory()->undefined_value();
930 }
931 if (!func->IsCallable()) {
932 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kPropertyNotFunction,
933 func, name, receiver),
934 Object);
935 }
936 return func;
937}
938
939namespace {
940
941MaybeHandle<FixedArray> CreateListFromArrayLikeFastPath(
942 Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
943 if (element_types == ElementTypes::kAll) {
944 if (object->IsJSArray()) {
945 Handle<JSArray> array = Handle<JSArray>::cast(object);
946 uint32_t length;
947 if (!array->HasArrayPrototype(isolate) ||
948 !array->length()->ToUint32(&length) || !array->HasFastElements() ||
949 !JSObject::PrototypeHasNoElements(isolate, *array)) {
950 return MaybeHandle<FixedArray>();
951 }
952 return array->GetElementsAccessor()->CreateListFromArrayLike(
953 isolate, array, length);
954 } else if (object->IsJSTypedArray()) {
955 Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(object);
956 size_t length = array->length();
957 if (array->WasDetached() ||
958 length > static_cast<size_t>(FixedArray::kMaxLength)) {
959 return MaybeHandle<FixedArray>();
960 }
961 return array->GetElementsAccessor()->CreateListFromArrayLike(
962 isolate, array, static_cast<uint32_t>(length));
963 }
964 }
965 return MaybeHandle<FixedArray>();
966}
967
968} // namespace
969
970// static
971MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
972 Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
973 // Fast-path for JSArray and JSTypedArray.
974 MaybeHandle<FixedArray> fast_result =
975 CreateListFromArrayLikeFastPath(isolate, object, element_types);
976 if (!fast_result.is_null()) return fast_result;
977 // 1. ReturnIfAbrupt(object).
978 // 2. (default elementTypes -- not applicable.)
979 // 3. If Type(obj) is not Object, throw a TypeError exception.
980 if (!object->IsJSReceiver()) {
981 THROW_NEW_ERROR(isolate,
982 NewTypeError(MessageTemplate::kCalledOnNonObject,
983 isolate->factory()->NewStringFromAsciiChecked(
984 "CreateListFromArrayLike")),
985 FixedArray);
986 }
987
988 // 4. Let len be ? ToLength(? Get(obj, "length")).
989 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
990 Handle<Object> raw_length_number;
991 ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
992 Object::GetLengthFromArrayLike(isolate, receiver),
993 FixedArray);
994 uint32_t len;
995 if (!raw_length_number->ToUint32(&len) ||
996 len > static_cast<uint32_t>(FixedArray::kMaxLength)) {
997 THROW_NEW_ERROR(isolate,
998 NewRangeError(MessageTemplate::kInvalidArrayLength),
999 FixedArray);
1000 }
1001 // 5. Let list be an empty List.
1002 Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
1003 // 6. Let index be 0.
1004 // 7. Repeat while index < len:
1005 for (uint32_t index = 0; index < len; ++index) {
1006 // 7a. Let indexName be ToString(index).
1007 // 7b. Let next be ? Get(obj, indexName).
1008 Handle<Object> next;
1009 ASSIGN_RETURN_ON_EXCEPTION(isolate, next,
1010 JSReceiver::GetElement(isolate, receiver, index),
1011 FixedArray);
1012 switch (element_types) {
1013 case ElementTypes::kAll:
1014 // Nothing to do.
1015 break;
1016 case ElementTypes::kStringAndSymbol: {
1017 // 7c. If Type(next) is not an element of elementTypes, throw a
1018 // TypeError exception.
1019 if (!next->IsName()) {
1020 THROW_NEW_ERROR(isolate,
1021 NewTypeError(MessageTemplate::kNotPropertyName, next),
1022 FixedArray);
1023 }
1024 // 7d. Append next as the last element of list.
1025 // Internalize on the fly so we can use pointer identity later.
1026 next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
1027 break;
1028 }
1029 }
1030 list->set(index, *next);
1031 // 7e. Set index to index + 1. (See loop header.)
1032 }
1033 // 8. Return list.
1034 return list;
1035}
1036
1037
1038// static
1039MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
1040 Handle<JSReceiver> object) {
1041 Handle<Object> val;
1042 Handle<Name> key = isolate->factory()->length_string();
1043 ASSIGN_RETURN_ON_EXCEPTION(
1044 isolate, val, JSReceiver::GetProperty(isolate, object, key), Object);
1045 return Object::ToLength(isolate, val);
1046}
1047
1048// static
1049MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
1050 OnNonExistent on_non_existent) {
1051 for (; it->IsFound(); it->Next()) {
1052 switch (it->state()) {
1053 case LookupIterator::NOT_FOUND:
1054 case LookupIterator::TRANSITION:
1055 UNREACHABLE();
1056 case LookupIterator::JSPROXY: {
1057 bool was_found;
1058 Handle<Object> receiver = it->GetReceiver();
1059 // In case of global IC, the receiver is the global object. Replace by
1060 // the global proxy.
1061 if (receiver->IsJSGlobalObject()) {
1062 receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(),
1063 it->isolate());
1064 }
1065 MaybeHandle<Object> result =
1066 JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
1067 it->GetName(), receiver, &was_found);
1068 if (!was_found) it->NotFound();
1069 return result;
1070 }
1071 case LookupIterator::INTERCEPTOR: {
1072 bool done;
1073 Handle<Object> result;
1074 ASSIGN_RETURN_ON_EXCEPTION(
1075 it->isolate(), result,
1076 JSObject::GetPropertyWithInterceptor(it, &done), Object);
1077 if (done) return result;
1078 break;
1079 }
1080 case LookupIterator::ACCESS_CHECK:
1081 if (it->HasAccess()) break;
1082 return JSObject::GetPropertyWithFailedAccessCheck(it);
1083 case LookupIterator::ACCESSOR:
1084 return GetPropertyWithAccessor(it);
1085 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1086 return it->isolate()->factory()->undefined_value();
1087 case LookupIterator::DATA:
1088 return it->GetDataValue();
1089 }
1090 }
1091
1092 if (on_non_existent == OnNonExistent::kThrowReferenceError) {
1093 THROW_NEW_ERROR(it->isolate(),
1094 NewReferenceError(MessageTemplate::kNotDefined, it->name()),
1095 Object);
1096 }
1097 return it->isolate()->factory()->undefined_value();
1098}
1099
1100
1101// static
1102MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
1103 Handle<JSProxy> proxy,
1104 Handle<Name> name,
1105 Handle<Object> receiver,
1106 bool* was_found) {
1107 *was_found = true;
1108
1109 DCHECK(!name->IsPrivate());
1110 STACK_CHECK(isolate, MaybeHandle<Object>());
1111 Handle<Name> trap_name = isolate->factory()->get_string();
1112 // 1. Assert: IsPropertyKey(P) is true.
1113 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
1114 Handle<Object> handler(proxy->handler(), isolate);
1115 // 3. If handler is null, throw a TypeError exception.
1116 // 4. Assert: Type(handler) is Object.
1117 if (proxy->IsRevoked()) {
1118 THROW_NEW_ERROR(isolate,
1119 NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1120 Object);
1121 }
1122 // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
1123 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
1124 // 6. Let trap be ? GetMethod(handler, "get").
1125 Handle<Object> trap;
1126 ASSIGN_RETURN_ON_EXCEPTION(
1127 isolate, trap,
1128 Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
1129 // 7. If trap is undefined, then
1130 if (trap->IsUndefined(isolate)) {
1131 // 7.a Return target.[[Get]](P, Receiver).
1132 LookupIterator it =
1133 LookupIterator::PropertyOrElement(isolate, receiver, name, target);
1134 MaybeHandle<Object> result = Object::GetProperty(&it);
1135 *was_found = it.IsFound();
1136 return result;
1137 }
1138 // 8. Let trapResult be ? Call(trap, handler, «target, P, Receiver»).
1139 Handle<Object> trap_result;
1140 Handle<Object> args[] = {target, name, receiver};
1141 ASSIGN_RETURN_ON_EXCEPTION(
1142 isolate, trap_result,
1143 Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
1144
1145 MaybeHandle<Object> result =
1146 JSProxy::CheckGetSetTrapResult(isolate, name, target, trap_result, kGet);
1147 if (result.is_null()) {
1148 return result;
1149 }
1150
1151 // 11. Return trap_result
1152 return trap_result;
1153}
1154
1155// static
1156MaybeHandle<Object> JSProxy::CheckGetSetTrapResult(Isolate* isolate,
1157 Handle<Name> name,
1158 Handle<JSReceiver> target,
1159 Handle<Object> trap_result,
1160 AccessKind access_kind) {
1161 // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
1162 PropertyDescriptor target_desc;
1163 Maybe<bool> target_found =
1164 JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
1165 MAYBE_RETURN_NULL(target_found);
1166 // 10. If targetDesc is not undefined, then
1167 if (target_found.FromJust()) {
1168 // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
1169 // false and targetDesc.[[Writable]] is false, then
1170 // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
1171 // throw a TypeError exception.
1172 bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
1173 !target_desc.configurable() &&
1174 !target_desc.writable() &&
1175 !trap_result->SameValue(*target_desc.value());
1176 if (inconsistent) {
1177 if (access_kind == kGet) {
1178 THROW_NEW_ERROR(
1179 isolate,
1180 NewTypeError(MessageTemplate::kProxyGetNonConfigurableData, name,
1181 target_desc.value(), trap_result),
1182 Object);
1183 } else {
1184 isolate->Throw(*isolate->factory()->NewTypeError(
1185 MessageTemplate::kProxySetFrozenData, name));
1186 return MaybeHandle<Object>();
1187 }
1188 }
1189 // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
1190 // is false and targetDesc.[[Get]] is undefined, then
1191 // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
1192 if (access_kind == kGet) {
1193 inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
1194 !target_desc.configurable() &&
1195 target_desc.get()->IsUndefined(isolate) &&
1196 !trap_result->IsUndefined(isolate);
1197 } else {
1198 inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
1199 !target_desc.configurable() &&
1200 target_desc.set()->IsUndefined(isolate);
1201 }
1202 if (inconsistent) {
1203 if (access_kind == kGet) {
1204 THROW_NEW_ERROR(
1205 isolate,
1206 NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor,
1207 name, trap_result),
1208 Object);
1209 } else {
1210 isolate->Throw(*isolate->factory()->NewTypeError(
1211 MessageTemplate::kProxySetFrozenAccessor, name));
1212 return MaybeHandle<Object>();
1213 }
1214 }
1215 }
1216 return isolate->factory()->undefined_value();
1217}
1218
1219
1220
1221bool Object::ToInt32(int32_t* value) {
1222 if (IsSmi()) {
1223 *value = Smi::ToInt(*this);
1224 return true;
1225 }
1226 if (IsHeapNumber()) {
1227 double num = HeapNumber::cast(*this)->value();
1228 // Check range before conversion to avoid undefined behavior.
1229 if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
1230 *value = FastD2I(num);
1231 return true;
1232 }
1233 }
1234 return false;
1235}
1236
1237// static constexpr object declarations need a definition to make the
1238// compiler happy.
1239constexpr Object Smi::kZero;
1240V8_EXPORT_PRIVATE constexpr Object SharedFunctionInfo::kNoSharedNameSentinel;
1241
1242Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
1243 Isolate* isolate, Handle<FunctionTemplateInfo> info,
1244 MaybeHandle<Name> maybe_name) {
1245 Object current_info = info->shared_function_info();
1246 if (current_info->IsSharedFunctionInfo()) {
1247 return handle(SharedFunctionInfo::cast(current_info), isolate);
1248 }
1249 Handle<Name> name;
1250 Handle<String> name_string;
1251 if (maybe_name.ToHandle(&name) && name->IsString()) {
1252 name_string = Handle<String>::cast(name);
1253 } else if (info->class_name()->IsString()) {
1254 name_string = handle(String::cast(info->class_name()), isolate);
1255 } else {
1256 name_string = isolate->factory()->empty_string();
1257 }
1258 FunctionKind function_kind;
1259 if (info->remove_prototype()) {
1260 function_kind = kConciseMethod;
1261 } else {
1262 function_kind = kNormalFunction;
1263 }
1264 Handle<SharedFunctionInfo> result =
1265 isolate->factory()->NewSharedFunctionInfoForApiFunction(name_string, info,
1266 function_kind);
1267
1268 result->set_length(info->length());
1269 result->DontAdaptArguments();
1270 DCHECK(result->IsApiFunction());
1271
1272 info->set_shared_function_info(*result);
1273 return result;
1274}
1275
1276bool FunctionTemplateInfo::IsTemplateFor(Map map) {
1277 // There is a constraint on the object; check.
1278 if (!map->IsJSObjectMap()) return false;
1279 // Fetch the constructor function of the object.
1280 Object cons_obj = map->GetConstructor();
1281 Object type;
1282 if (cons_obj->IsJSFunction()) {
1283 JSFunction fun = JSFunction::cast(cons_obj);
1284 type = fun->shared()->function_data();
1285 } else if (cons_obj->IsFunctionTemplateInfo()) {
1286 type = FunctionTemplateInfo::cast(cons_obj);
1287 } else {
1288 return false;
1289 }
1290 // Iterate through the chain of inheriting function templates to
1291 // see if the required one occurs.
1292 while (type->IsFunctionTemplateInfo()) {
1293 if (type == *this) return true;
1294 type = FunctionTemplateInfo::cast(type)->GetParentTemplate();
1295 }
1296 // Didn't find the required type in the inheritance chain.
1297 return false;
1298}
1299
1300// static
1301FunctionTemplateRareData FunctionTemplateInfo::AllocateFunctionTemplateRareData(
1302 Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) {
1303 DCHECK(function_template_info->rare_data()->IsUndefined(isolate));
1304 Handle<Struct> struct_obj = isolate->factory()->NewStruct(
1305 FUNCTION_TEMPLATE_RARE_DATA_TYPE, AllocationType::kOld);
1306 Handle<FunctionTemplateRareData> rare_data =
1307 i::Handle<FunctionTemplateRareData>::cast(struct_obj);
1308 function_template_info->set_rare_data(*rare_data);
1309 return *rare_data;
1310}
1311
1312// static
1313Handle<TemplateList> TemplateList::New(Isolate* isolate, int size) {
1314 Handle<FixedArray> list =
1315 isolate->factory()->NewFixedArray(kLengthIndex + size);
1316 list->set(kLengthIndex, Smi::kZero);
1317 return Handle<TemplateList>::cast(list);
1318}
1319
1320// static
1321Handle<TemplateList> TemplateList::Add(Isolate* isolate,
1322 Handle<TemplateList> list,
1323 Handle<i::Object> value) {
1324 STATIC_ASSERT(kFirstElementIndex == 1);
1325 int index = list->length() + 1;
1326 Handle<i::FixedArray> fixed_array = Handle<FixedArray>::cast(list);
1327 fixed_array = FixedArray::SetAndGrow(isolate, fixed_array, index, value);
1328 fixed_array->set(kLengthIndex, Smi::FromInt(index));
1329 return Handle<TemplateList>::cast(fixed_array);
1330}
1331
1332
1333// ES6 9.5.1
1334// static
1335MaybeHandle<HeapObject> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
1336 Isolate* isolate = proxy->GetIsolate();
1337 Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
1338
1339 STACK_CHECK(isolate, MaybeHandle<HeapObject>());
1340
1341 // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
1342 // 2. If handler is null, throw a TypeError exception.
1343 // 3. Assert: Type(handler) is Object.
1344 // 4. Let target be the value of the [[ProxyTarget]] internal slot.
1345 if (proxy->IsRevoked()) {
1346 THROW_NEW_ERROR(isolate,
1347 NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
1348 HeapObject);
1349 }
1350 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
1351 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
1352
1353 // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
1354 Handle<Object> trap;
1355 ASSIGN_RETURN_ON_EXCEPTION(isolate, trap,
1356 Object::GetMethod(handler, trap_name), HeapObject);
1357 // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
1358 if (trap->IsUndefined(isolate)) {
1359 return JSReceiver::GetPrototype(isolate, target);
1360 }
1361 // 7. Let handlerProto be ? Call(trap, handler, «target»).
1362 Handle<Object> argv[] = {target};
1363 Handle<Object> handler_proto;
1364 ASSIGN_RETURN_ON_EXCEPTION(
1365 isolate, handler_proto,
1366 Execution::Call(isolate, trap, handler, arraysize(argv), argv),
1367 HeapObject);
1368 // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
1369 if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
1370 THROW_NEW_ERROR(isolate,
1371 NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
1372 HeapObject);
1373 }
1374 // 9. Let extensibleTarget be ? IsExtensible(target).
1375 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
1376 MAYBE_RETURN(is_extensible, MaybeHandle<HeapObject>());
1377 // 10. If extensibleTarget is true, return handlerProto.
1378 if (is_extensible.FromJust()) return Handle<HeapObject>::cast(handler_proto);
1379 // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
1380 Handle<HeapObject> target_proto;
1381 ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
1382 JSReceiver::GetPrototype(isolate, target),
1383 HeapObject);
1384 // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
1385 if (!handler_proto->SameValue(*target_proto)) {
1386 THROW_NEW_ERROR(
1387 isolate,
1388 NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
1389 HeapObject);
1390 }
1391 // 13. Return handlerProto.
1392 return Handle<HeapObject>::cast(handler_proto);
1393}
1394
1395MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
1396 Isolate* isolate = it->isolate();
1397 Handle<Object> structure = it->GetAccessors();
1398 Handle<Object> receiver = it->GetReceiver();
1399 // In case of global IC, the receiver is the global object. Replace by the
1400 // global proxy.
1401 if (receiver->IsJSGlobalObject()) {
1402 receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(), isolate);
1403 }
1404
1405 // We should never get here to initialize a const with the hole value since a
1406 // const declaration would conflict with the getter.
1407 DCHECK(!structure->IsForeign());
1408
1409 // API style callbacks.
1410 Handle<JSObject> holder = it->GetHolder<JSObject>();
1411 if (structure->IsAccessorInfo()) {
1412 Handle<Name> name = it->GetName();
1413 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1414 if (!info->IsCompatibleReceiver(*receiver)) {
1415 THROW_NEW_ERROR(isolate,
1416 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1417 name, receiver),
1418 Object);
1419 }
1420
1421 if (!info->has_getter()) return isolate->factory()->undefined_value();
1422
1423 if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1424 ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
1425 Object::ConvertReceiver(isolate, receiver),
1426 Object);
1427 }
1428
1429 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1430 Just(kDontThrow));
1431 Handle<Object> result = args.CallAccessorGetter(info, name);
1432 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1433 if (result.is_null()) return isolate->factory()->undefined_value();
1434 Handle<Object> reboxed_result = handle(*result, isolate);
1435 if (info->replace_on_access() && receiver->IsJSReceiver()) {
1436 RETURN_ON_EXCEPTION(isolate,
1437 Accessors::ReplaceAccessorWithDataProperty(
1438 receiver, holder, name, result),
1439 Object);
1440 }
1441 return reboxed_result;
1442 }
1443
1444 // AccessorPair with 'cached' private property.
1445 if (it->TryLookupCachedProperty()) {
1446 return Object::GetProperty(it);
1447 }
1448
1449 // Regular accessor.
1450 Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
1451 if (getter->IsFunctionTemplateInfo()) {
1452 SaveAndSwitchContext save(isolate, *holder->GetCreationContext());
1453 return Builtins::InvokeApiFunction(
1454 isolate, false, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
1455 nullptr, isolate->factory()->undefined_value());
1456 } else if (getter->IsCallable()) {
1457 // TODO(rossberg): nicer would be to cast to some JSCallable here...
1458 return Object::GetPropertyWithDefinedGetter(
1459 receiver, Handle<JSReceiver>::cast(getter));
1460 }
1461 // Getter is not a function.
1462 return isolate->factory()->undefined_value();
1463}
1464
1465// static
1466Address AccessorInfo::redirect(Address address, AccessorComponent component) {
1467 ApiFunction fun(address);
1468 DCHECK_EQ(ACCESSOR_GETTER, component);
1469 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
1470 return ExternalReference::Create(&fun, type).address();
1471}
1472
1473Address AccessorInfo::redirected_getter() const {
1474 Address accessor = v8::ToCData<Address>(getter());
1475 if (accessor == kNullAddress) return kNullAddress;
1476 return redirect(accessor, ACCESSOR_GETTER);
1477}
1478
1479Address CallHandlerInfo::redirected_callback() const {
1480 Address address = v8::ToCData<Address>(callback());
1481 ApiFunction fun(address);
1482 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
1483 return ExternalReference::Create(&fun, type).address();
1484}
1485
1486bool AccessorInfo::IsCompatibleReceiverMap(Handle<AccessorInfo> info,
1487 Handle<Map> map) {
1488 if (!info->HasExpectedReceiverType()) return true;
1489 if (!map->IsJSObjectMap()) return false;
1490 return FunctionTemplateInfo::cast(info->expected_receiver_type())
1491 ->IsTemplateFor(*map);
1492}
1493
1494Maybe<bool> Object::SetPropertyWithAccessor(
1495 LookupIterator* it, Handle<Object> value,
1496 Maybe<ShouldThrow> maybe_should_throw) {
1497 Isolate* isolate = it->isolate();
1498 Handle<Object> structure = it->GetAccessors();
1499 Handle<Object> receiver = it->GetReceiver();
1500 // In case of global IC, the receiver is the global object. Replace by the
1501 // global proxy.
1502 if (receiver->IsJSGlobalObject()) {
1503 receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(), isolate);
1504 }
1505
1506 // We should never get here to initialize a const with the hole value since a
1507 // const declaration would conflict with the setter.
1508 DCHECK(!structure->IsForeign());
1509
1510 // API style callbacks.
1511 Handle<JSObject> holder = it->GetHolder<JSObject>();
1512 if (structure->IsAccessorInfo()) {
1513 Handle<Name> name = it->GetName();
1514 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
1515 if (!info->IsCompatibleReceiver(*receiver)) {
1516 isolate->Throw(*isolate->factory()->NewTypeError(
1517 MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
1518 return Nothing<bool>();
1519 }
1520
1521 if (!info->has_setter()) {
1522 // TODO(verwaest): We should not get here anymore once all AccessorInfos
1523 // are marked as special_data_property. They cannot both be writable and
1524 // not have a setter.
1525 return Just(true);
1526 }
1527
1528 if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1529 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1530 isolate, receiver, Object::ConvertReceiver(isolate, receiver),
1531 Nothing<bool>());
1532 }
1533
1534 // The actual type of setter callback is either
1535 // v8::AccessorNameSetterCallback or
1536 // i::Accesors::AccessorNameBooleanSetterCallback, depending on whether the
1537 // AccessorInfo was created by the API or internally (see accessors.cc).
1538 // Here we handle both cases using GenericNamedPropertySetterCallback and
1539 // its Call method.
1540 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
1541 maybe_should_throw);
1542 Handle<Object> result = args.CallAccessorSetter(info, name, value);
1543 // In the case of AccessorNameSetterCallback, we know that the result value
1544 // cannot have been set, so the result of Call will be null. In the case of
1545 // AccessorNameBooleanSetterCallback, the result will either be null
1546 // (signalling an exception) or a boolean Oddball.
1547 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
1548 if (result.is_null()) return Just(true);
1549 DCHECK(result->BooleanValue(isolate) ||
1550 GetShouldThrow(isolate, maybe_should_throw) == kDontThrow);
1551 return Just(result->BooleanValue(isolate));
1552 }
1553
1554 // Regular accessor.
1555 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
1556 if (setter->IsFunctionTemplateInfo()) {
1557 SaveAndSwitchContext save(isolate, *holder->GetCreationContext());
1558 Handle<Object> argv[] = {value};
1559 RETURN_ON_EXCEPTION_VALUE(
1560 isolate, Builtins::InvokeApiFunction(
1561 isolate, false, Handle<FunctionTemplateInfo>::cast(setter),
1562 receiver, arraysize(argv), argv,
1563 isolate->factory()->undefined_value()),
1564 Nothing<bool>());
1565 return Just(true);
1566 } else if (setter->IsCallable()) {
1567 // TODO(rossberg): nicer would be to cast to some JSCallable here...
1568 return SetPropertyWithDefinedSetter(
1569 receiver, Handle<JSReceiver>::cast(setter), value, maybe_should_throw);
1570 }
1571
1572 RETURN_FAILURE(isolate, GetShouldThrow(isolate, maybe_should_throw),
1573 NewTypeError(MessageTemplate::kNoSetterInCallback,
1574 it->GetName(), it->GetHolder<JSObject>()));
1575}
1576
1577MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
1578 Handle<Object> receiver,
1579 Handle<JSReceiver> getter) {
1580 Isolate* isolate = getter->GetIsolate();
1581
1582 // Platforms with simulators like arm/arm64 expose a funny issue. If the
1583 // simulator has a separate JS stack pointer from the C++ stack pointer, it
1584 // can miss C++ stack overflows in the stack guard at the start of JavaScript
1585 // functions. It would be very expensive to check the C++ stack pointer at
1586 // that location. The best solution seems to be to break the impasse by
1587 // adding checks at possible recursion points. What's more, we don't put
1588 // this stack check behind the USE_SIMULATOR define in order to keep
1589 // behavior the same between hardware and simulators.
1590 StackLimitCheck check(isolate);
1591 if (check.JsHasOverflowed()) {
1592 isolate->StackOverflow();
1593 return MaybeHandle<Object>();
1594 }
1595
1596 return Execution::Call(isolate, getter, receiver, 0, nullptr);
1597}
1598
1599Maybe<bool> Object::SetPropertyWithDefinedSetter(
1600 Handle<Object> receiver, Handle<JSReceiver> setter, Handle<Object> value,
1601 Maybe<ShouldThrow> should_throw) {
1602 Isolate* isolate = setter->GetIsolate();
1603
1604 Handle<Object> argv[] = { value };
1605 RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver,
1606 arraysize(argv), argv),
1607 Nothing<bool>());
1608 return Just(true);
1609}
1610
1611Map Object::GetPrototypeChainRootMap(Isolate* isolate) const {
1612 DisallowHeapAllocation no_alloc;
1613 if (IsSmi()) {
1614 Context native_context = isolate->context()->native_context();
1615 return native_context->number_function()->initial_map();
1616 }
1617
1618 const HeapObject heap_object = HeapObject::cast(*this);
1619 return heap_object->map()->GetPrototypeChainRootMap(isolate);
1620}
1621
1622Smi Object::GetOrCreateHash(Isolate* isolate) {
1623 DisallowHeapAllocation no_gc;
1624 Object hash = Object::GetSimpleHash(*this);
1625 if (hash->IsSmi()) return Smi::cast(hash);
1626
1627 DCHECK(IsJSReceiver());
1628 return JSReceiver::cast(*this)->GetOrCreateIdentityHash(isolate);
1629}
1630
1631bool Object::SameValue(Object other) {
1632 if (other == *this) return true;
1633
1634 if (IsNumber() && other->IsNumber()) {
1635 return SameNumberValue(Number(), other->Number());
1636 }
1637 if (IsString() && other->IsString()) {
1638 return String::cast(*this)->Equals(String::cast(other));
1639 }
1640 if (IsBigInt() && other->IsBigInt()) {
1641 return BigInt::EqualToBigInt(BigInt::cast(*this), BigInt::cast(other));
1642 }
1643 return false;
1644}
1645
1646bool Object::SameValueZero(Object other) {
1647 if (other == *this) return true;
1648
1649 if (IsNumber() && other->IsNumber()) {
1650 double this_value = Number();
1651 double other_value = other->Number();
1652 // +0 == -0 is true
1653 return this_value == other_value ||
1654 (std::isnan(this_value) && std::isnan(other_value));
1655 }
1656 if (IsString() && other->IsString()) {
1657 return String::cast(*this)->Equals(String::cast(other));
1658 }
1659 if (IsBigInt() && other->IsBigInt()) {
1660 return BigInt::EqualToBigInt(BigInt::cast(*this), BigInt::cast(other));
1661 }
1662 return false;
1663}
1664
1665MaybeHandle<Object> Object::ArraySpeciesConstructor(
1666 Isolate* isolate, Handle<Object> original_array) {
1667 Handle<Object> default_species = isolate->array_function();
1668 if (original_array->IsJSArray() &&
1669 Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
1670 isolate->IsArraySpeciesLookupChainIntact()) {
1671 return default_species;
1672 }
1673 Handle<Object> constructor = isolate->factory()->undefined_value();
1674 Maybe<bool> is_array = Object::IsArray(original_array);
1675 MAYBE_RETURN_NULL(is_array);
1676 if (is_array.FromJust()) {
1677 ASSIGN_RETURN_ON_EXCEPTION(
1678 isolate, constructor,
1679 Object::GetProperty(isolate, original_array,
1680 isolate->factory()->constructor_string()),
1681 Object);
1682 if (constructor->IsConstructor()) {
1683 Handle<Context> constructor_context;
1684 ASSIGN_RETURN_ON_EXCEPTION(
1685 isolate, constructor_context,
1686 JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
1687 Object);
1688 if (*constructor_context != *isolate->native_context() &&
1689 *constructor == constructor_context->array_function()) {
1690 constructor = isolate->factory()->undefined_value();
1691 }
1692 }
1693 if (constructor->IsJSReceiver()) {
1694 ASSIGN_RETURN_ON_EXCEPTION(
1695 isolate, constructor,
1696 JSReceiver::GetProperty(isolate,
1697 Handle<JSReceiver>::cast(constructor),
1698 isolate->factory()->species_symbol()),
1699 Object);
1700 if (constructor->IsNull(isolate)) {
1701 constructor = isolate->factory()->undefined_value();
1702 }
1703 }
1704 }
1705 if (constructor->IsUndefined(isolate)) {
1706 return default_species;
1707 } else {
1708 if (!constructor->IsConstructor()) {
1709 THROW_NEW_ERROR(isolate,
1710 NewTypeError(MessageTemplate::kSpeciesNotConstructor),
1711 Object);
1712 }
1713 return constructor;
1714 }
1715}
1716
1717// ES6 section 7.3.20 SpeciesConstructor ( O, defaultConstructor )
1718V8_WARN_UNUSED_RESULT MaybeHandle<Object> Object::SpeciesConstructor(
1719 Isolate* isolate, Handle<JSReceiver> recv,
1720 Handle<JSFunction> default_ctor) {
1721 Handle<Object> ctor_obj;
1722 ASSIGN_RETURN_ON_EXCEPTION(
1723 isolate, ctor_obj,
1724 JSObject::GetProperty(isolate, recv,
1725 isolate->factory()->constructor_string()),
1726 Object);
1727
1728 if (ctor_obj->IsUndefined(isolate)) return default_ctor;
1729
1730 if (!ctor_obj->IsJSReceiver()) {
1731 THROW_NEW_ERROR(isolate,
1732 NewTypeError(MessageTemplate::kConstructorNotReceiver),
1733 Object);
1734 }
1735
1736 Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj);
1737
1738 Handle<Object> species;
1739 ASSIGN_RETURN_ON_EXCEPTION(
1740 isolate, species,
1741 JSObject::GetProperty(isolate, ctor,
1742 isolate->factory()->species_symbol()),
1743 Object);
1744
1745 if (species->IsNullOrUndefined(isolate)) {
1746 return default_ctor;
1747 }
1748
1749 if (species->IsConstructor()) return species;
1750
1751 THROW_NEW_ERROR(
1752 isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object);
1753}
1754
1755bool Object::IterationHasObservableEffects() {
1756 // Check that this object is an array.
1757 if (!IsJSArray()) return true;
1758 JSArray array = JSArray::cast(*this);
1759 Isolate* isolate = array->GetIsolate();
1760
1761#ifdef V8_ENABLE_FORCE_SLOW_PATH
1762 if (isolate->force_slow_path()) return true;
1763#endif
1764
1765 // Check that we have the original ArrayPrototype.
1766 if (!array->map()->prototype()->IsJSObject()) return true;
1767 JSObject array_proto = JSObject::cast(array->map()->prototype());
1768 if (!isolate->is_initial_array_prototype(array_proto)) return true;
1769
1770 // Check that the ArrayPrototype hasn't been modified in a way that would
1771 // affect iteration.
1772 if (!isolate->IsArrayIteratorLookupChainIntact()) return true;
1773
1774 // For FastPacked kinds, iteration will have the same effect as simply
1775 // accessing each property in order.
1776 ElementsKind array_kind = array->GetElementsKind();
1777 if (IsFastPackedElementsKind(array_kind)) return false;
1778
1779 // For FastHoley kinds, an element access on a hole would cause a lookup on
1780 // the prototype. This could have different results if the prototype has been
1781 // changed.
1782 if (IsHoleyElementsKind(array_kind) &&
1783 isolate->IsNoElementsProtectorIntact()) {
1784 return false;
1785 }
1786 return true;
1787}
1788
1789void Object::ShortPrint(FILE* out) const {
1790 OFStream os(out);
1791 os << Brief(*this);
1792}
1793
1794void Object::ShortPrint(StringStream* accumulator) const {
1795 std::ostringstream os;
1796 os << Brief(*this);
1797 accumulator->Add(os.str().c_str());
1798}
1799
1800void Object::ShortPrint(std::ostream& os) const { os << Brief(*this); }
1801
1802std::ostream& operator<<(std::ostream& os, const Object& obj) {
1803 obj.ShortPrint(os);
1804 return os;
1805}
1806
1807void MaybeObject::ShortPrint(FILE* out) {
1808 OFStream os(out);
1809 os << Brief(*this);
1810}
1811
1812void MaybeObject::ShortPrint(StringStream* accumulator) {
1813 std::ostringstream os;
1814 os << Brief(*this);
1815 accumulator->Add(os.str().c_str());
1816}
1817
1818void MaybeObject::ShortPrint(std::ostream& os) { os << Brief(*this); }
1819
1820Brief::Brief(const Object v) : value(v->ptr()) {}
1821Brief::Brief(const MaybeObject v) : value(v.ptr()) {}
1822
1823std::ostream& operator<<(std::ostream& os, const Brief& v) {
1824 MaybeObject maybe_object(v.value);
1825 Smi smi;
1826 HeapObject heap_object;
1827 if (maybe_object->ToSmi(&smi)) {
1828 smi->SmiPrint(os);
1829 } else if (maybe_object->IsCleared()) {
1830 os << "[cleared]";
1831 } else if (maybe_object->GetHeapObjectIfWeak(&heap_object)) {
1832 os << "[weak] ";
1833 heap_object->HeapObjectShortPrint(os);
1834 } else if (maybe_object->GetHeapObjectIfStrong(&heap_object)) {
1835 heap_object->HeapObjectShortPrint(os);
1836 } else {
1837 UNREACHABLE();
1838 }
1839 return os;
1840}
1841
1842void Smi::SmiPrint(std::ostream& os) const { // NOLINT
1843 os << value();
1844}
1845
1846
1847
1848void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
1849 os << AsHex::Address(this->ptr()) << " ";
1850
1851 if (IsString()) {
1852 HeapStringAllocator allocator;
1853 StringStream accumulator(&allocator);
1854 String::cast(*this)->StringShortPrint(&accumulator);
1855 os << accumulator.ToCString().get();
1856 return;
1857 }
1858 if (IsJSObject()) {
1859 HeapStringAllocator allocator;
1860 StringStream accumulator(&allocator);
1861 JSObject::cast(*this)->JSObjectShortPrint(&accumulator);
1862 os << accumulator.ToCString().get();
1863 return;
1864 }
1865 switch (map()->instance_type()) {
1866 case MAP_TYPE: {
1867 os << "<Map";
1868 Map mapInstance = Map::cast(*this);
1869 if (mapInstance->IsJSObjectMap()) {
1870 os << "(" << ElementsKindToString(mapInstance->elements_kind()) << ")";
1871 } else if (mapInstance->instance_size() != kVariableSizeSentinel) {
1872 os << "[" << mapInstance->instance_size() << "]";
1873 }
1874 os << ">";
1875 } break;
1876 case AWAIT_CONTEXT_TYPE: {
1877 os << "<AwaitContext generator= ";
1878 HeapStringAllocator allocator;
1879 StringStream accumulator(&allocator);
1880 Context::cast(*this)->extension()->ShortPrint(&accumulator);
1881 os << accumulator.ToCString().get();
1882 os << '>';
1883 break;
1884 }
1885 case BLOCK_CONTEXT_TYPE:
1886 os << "<BlockContext[" << Context::cast(*this)->length() << "]>";
1887 break;
1888 case CATCH_CONTEXT_TYPE:
1889 os << "<CatchContext[" << Context::cast(*this)->length() << "]>";
1890 break;
1891 case DEBUG_EVALUATE_CONTEXT_TYPE:
1892 os << "<DebugEvaluateContext[" << Context::cast(*this)->length() << "]>";
1893 break;
1894 case EVAL_CONTEXT_TYPE:
1895 os << "<EvalContext[" << Context::cast(*this)->length() << "]>";
1896 break;
1897 case FUNCTION_CONTEXT_TYPE:
1898 os << "<FunctionContext[" << Context::cast(*this)->length() << "]>";
1899 break;
1900 case MODULE_CONTEXT_TYPE:
1901 os << "<ModuleContext[" << Context::cast(*this)->length() << "]>";
1902 break;
1903 case NATIVE_CONTEXT_TYPE:
1904 os << "<NativeContext[" << Context::cast(*this)->length() << "]>";
1905 break;
1906 case SCRIPT_CONTEXT_TYPE:
1907 os << "<ScriptContext[" << Context::cast(*this)->length() << "]>";
1908 break;
1909 case WITH_CONTEXT_TYPE:
1910 os << "<WithContext[" << Context::cast(*this)->length() << "]>";
1911 break;
1912 case SCRIPT_CONTEXT_TABLE_TYPE:
1913 os << "<ScriptContextTable[" << FixedArray::cast(*this)->length() << "]>";
1914 break;
1915 case HASH_TABLE_TYPE:
1916 os << "<HashTable[" << FixedArray::cast(*this)->length() << "]>";
1917 break;
1918 case ORDERED_HASH_MAP_TYPE:
1919 os << "<OrderedHashMap[" << FixedArray::cast(*this)->length() << "]>";
1920 break;
1921 case ORDERED_HASH_SET_TYPE:
1922 os << "<OrderedHashSet[" << FixedArray::cast(*this)->length() << "]>";
1923 break;
1924 case ORDERED_NAME_DICTIONARY_TYPE:
1925 os << "<OrderedNameDictionary[" << FixedArray::cast(*this)->length()
1926 << "]>";
1927 break;
1928 case NAME_DICTIONARY_TYPE:
1929 os << "<NameDictionary[" << FixedArray::cast(*this)->length() << "]>";
1930 break;
1931 case GLOBAL_DICTIONARY_TYPE:
1932 os << "<GlobalDictionary[" << FixedArray::cast(*this)->length() << "]>";
1933 break;
1934 case NUMBER_DICTIONARY_TYPE:
1935 os << "<NumberDictionary[" << FixedArray::cast(*this)->length() << "]>";
1936 break;
1937 case SIMPLE_NUMBER_DICTIONARY_TYPE:
1938 os << "<SimpleNumberDictionary[" << FixedArray::cast(*this)->length()
1939 << "]>";
1940 break;
1941 case STRING_TABLE_TYPE:
1942 os << "<StringTable[" << FixedArray::cast(*this)->length() << "]>";
1943 break;
1944 case FIXED_ARRAY_TYPE:
1945 os << "<FixedArray[" << FixedArray::cast(*this)->length() << "]>";
1946 break;
1947 case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
1948 os << "<ObjectBoilerplateDescription["
1949 << FixedArray::cast(*this)->length() << "]>";
1950 break;
1951 case FIXED_DOUBLE_ARRAY_TYPE:
1952 os << "<FixedDoubleArray[" << FixedDoubleArray::cast(*this)->length()
1953 << "]>";
1954 break;
1955 case BYTE_ARRAY_TYPE:
1956 os << "<ByteArray[" << ByteArray::cast(*this)->length() << "]>";
1957 break;
1958 case BYTECODE_ARRAY_TYPE:
1959 os << "<BytecodeArray[" << BytecodeArray::cast(*this)->length() << "]>";
1960 break;
1961 case DESCRIPTOR_ARRAY_TYPE:
1962 os << "<DescriptorArray["
1963 << DescriptorArray::cast(*this)->number_of_descriptors() << "]>";
1964 break;
1965 case TRANSITION_ARRAY_TYPE:
1966 os << "<TransitionArray[" << TransitionArray::cast(*this)->length()
1967 << "]>";
1968 break;
1969 case PROPERTY_ARRAY_TYPE:
1970 os << "<PropertyArray[" << PropertyArray::cast(*this)->length() << "]>";
1971 break;
1972 case FEEDBACK_CELL_TYPE: {
1973 {
1974 ReadOnlyRoots roots = GetReadOnlyRoots();
1975 os << "<FeedbackCell[";
1976 if (map() == roots.no_closures_cell_map()) {
1977 os << "no feedback";
1978 } else if (map() == roots.no_closures_cell_map()) {
1979 os << "no closures";
1980 } else if (map() == roots.one_closure_cell_map()) {
1981 os << "one closure";
1982 } else if (map() == roots.many_closures_cell_map()) {
1983 os << "many closures";
1984 } else {
1985 os << "!!!INVALID MAP!!!";
1986 }
1987 os << "]>";
1988 }
1989 break;
1990 }
1991 case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
1992 os << "<ClosureFeedbackCellArray["
1993 << ClosureFeedbackCellArray::cast(*this)->length() << "]>";
1994 break;
1995 case FEEDBACK_VECTOR_TYPE:
1996 os << "<FeedbackVector[" << FeedbackVector::cast(*this)->length() << "]>";
1997 break;
1998 case FREE_SPACE_TYPE:
1999 os << "<FreeSpace[" << FreeSpace::cast(*this)->size() << "]>";
2000 break;
2001#define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype) \
2002 case FIXED_##TYPE##_ARRAY_TYPE: \
2003 os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(*this)->length() \
2004 << "]>"; \
2005 break;
2006
2007 TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
2008#undef TYPED_ARRAY_SHORT_PRINT
2009
2010 case PREPARSE_DATA_TYPE: {
2011 PreparseData data = PreparseData::cast(*this);
2012 os << "<PreparseData[data=" << data->data_length()
2013 << " children=" << data->children_length() << "]>";
2014 break;
2015 }
2016
2017 case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE: {
2018 UncompiledDataWithoutPreparseData data =
2019 UncompiledDataWithoutPreparseData::cast(*this);
2020 os << "<UncompiledDataWithoutPreparseData (" << data->start_position()
2021 << ", " << data->end_position() << ")]>";
2022 break;
2023 }
2024
2025 case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE: {
2026 UncompiledDataWithPreparseData data =
2027 UncompiledDataWithPreparseData::cast(*this);
2028 os << "<UncompiledDataWithPreparseData (" << data->start_position()
2029 << ", " << data->end_position()
2030 << ") preparsed=" << Brief(data->preparse_data()) << ">";
2031 break;
2032 }
2033
2034 case SHARED_FUNCTION_INFO_TYPE: {
2035 SharedFunctionInfo shared = SharedFunctionInfo::cast(*this);
2036 std::unique_ptr<char[]> debug_name = shared->DebugName()->ToCString();
2037 if (debug_name[0] != 0) {
2038 os << "<SharedFunctionInfo " << debug_name.get() << ">";
2039 } else {
2040 os << "<SharedFunctionInfo>";
2041 }
2042 break;
2043 }
2044 case JS_MESSAGE_OBJECT_TYPE:
2045 os << "<JSMessageObject>";
2046 break;
2047#define MAKE_STRUCT_CASE(TYPE, Name, name) \
2048 case TYPE: \
2049 os << "<" #Name; \
2050 Name::cast(*this)->BriefPrintDetails(os); \
2051 os << ">"; \
2052 break;
2053