blob: f09f42d5f0480f76b8d6ac4c0e54efb0f6a9314e [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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/api-natives.h"
6
7#include "src/api.h"
8#include "src/isolate-inl.h"
9#include "src/lookup.h"
10#include "src/messages.h"
11
12namespace v8 {
13namespace internal {
14
15
16namespace {
17
18MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
Ben Murdoch097c5b22016-05-18 11:27:45 +010019 Handle<ObjectTemplateInfo> data,
Ben Murdochc5610432016-08-08 18:44:38 +010020 Handle<JSReceiver> new_target,
Ben Murdoch097c5b22016-05-18 11:27:45 +010021 bool is_hidden_prototype);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022
23MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
24 Handle<FunctionTemplateInfo> data,
25 Handle<Name> name = Handle<Name>());
26
27
28MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data,
29 Handle<Name> name = Handle<Name>()) {
30 if (data->IsFunctionTemplateInfo()) {
31 return InstantiateFunction(isolate,
32 Handle<FunctionTemplateInfo>::cast(data), name);
33 } else if (data->IsObjectTemplateInfo()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010034 return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data),
Ben Murdochc5610432016-08-08 18:44:38 +010035 Handle<JSReceiver>(), false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 } else {
37 return data;
38 }
39}
40
Ben Murdoch097c5b22016-05-18 11:27:45 +010041MaybeHandle<Object> DefineAccessorProperty(
42 Isolate* isolate, Handle<JSObject> object, Handle<Name> name,
43 Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes,
44 bool force_instantiate) {
45 DCHECK(!getter->IsFunctionTemplateInfo() ||
46 !FunctionTemplateInfo::cast(*getter)->do_not_cache());
47 DCHECK(!setter->IsFunctionTemplateInfo() ||
48 !FunctionTemplateInfo::cast(*setter)->do_not_cache());
49 if (force_instantiate) {
50 if (getter->IsFunctionTemplateInfo()) {
51 ASSIGN_RETURN_ON_EXCEPTION(
52 isolate, getter,
53 InstantiateFunction(isolate,
54 Handle<FunctionTemplateInfo>::cast(getter)),
55 Object);
56 }
57 if (setter->IsFunctionTemplateInfo()) {
58 ASSIGN_RETURN_ON_EXCEPTION(
59 isolate, setter,
60 InstantiateFunction(isolate,
61 Handle<FunctionTemplateInfo>::cast(setter)),
62 Object);
63 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 }
65 RETURN_ON_EXCEPTION(isolate, JSObject::DefineAccessor(object, name, getter,
66 setter, attributes),
67 Object);
68 return object;
69}
70
71
72MaybeHandle<Object> DefineDataProperty(Isolate* isolate,
73 Handle<JSObject> object,
74 Handle<Name> name,
75 Handle<Object> prop_data,
76 PropertyAttributes attributes) {
77 Handle<Object> value;
78 ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
79 Instantiate(isolate, prop_data, name), Object);
80
81 LookupIterator it = LookupIterator::PropertyOrElement(
82 isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
83
84#ifdef DEBUG
85 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
86 DCHECK(maybe.IsJust());
87 if (it.IsFound()) {
88 THROW_NEW_ERROR(
89 isolate,
90 NewTypeError(MessageTemplate::kDuplicateTemplateProperty, name),
91 Object);
92 }
93#endif
94
95 MAYBE_RETURN_NULL(
96 Object::AddDataProperty(&it, value, attributes, Object::THROW_ON_ERROR,
97 Object::CERTAINLY_NOT_STORE_FROM_KEYED));
98 return value;
99}
100
101
102void DisableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
103 Handle<Map> old_map(object->map());
104 // Copy map so it won't interfere constructor's initial map.
105 Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
106 new_map->set_is_access_check_needed(false);
107 JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
108}
109
110
111void EnableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
112 Handle<Map> old_map(object->map());
113 // Copy map so it won't interfere constructor's initial map.
114 Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
115 new_map->set_is_access_check_needed(true);
116 JSObject::MigrateToMap(object, new_map);
117}
118
119
120class AccessCheckDisableScope {
121 public:
122 AccessCheckDisableScope(Isolate* isolate, Handle<JSObject> obj)
123 : isolate_(isolate),
124 disabled_(obj->map()->is_access_check_needed()),
125 obj_(obj) {
126 if (disabled_) {
127 DisableAccessChecks(isolate_, obj_);
128 }
129 }
130 ~AccessCheckDisableScope() {
131 if (disabled_) {
132 EnableAccessChecks(isolate_, obj_);
133 }
134 }
135
136 private:
137 Isolate* isolate_;
138 const bool disabled_;
139 Handle<JSObject> obj_;
140};
141
142
143Object* GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) {
144 Handle<Context> native_context = isolate->native_context();
145 DCHECK(!native_context.is_null());
146 switch (intrinsic) {
147#define GET_INTRINSIC_VALUE(name, iname) \
148 case v8::k##name: \
149 return native_context->iname();
150 V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE)
151#undef GET_INTRINSIC_VALUE
152 }
153 return nullptr;
154}
155
Ben Murdoch097c5b22016-05-18 11:27:45 +0100156// Returns parent function template or null.
157FunctionTemplateInfo* GetParent(FunctionTemplateInfo* data) {
158 Object* parent = data->parent_template();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100159 return parent->IsUndefined(data->GetIsolate())
160 ? nullptr
161 : FunctionTemplateInfo::cast(parent);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100162}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000163
Ben Murdoch097c5b22016-05-18 11:27:45 +0100164// Starting from given object template's constructor walk up the inheritance
165// chain till a function template that has an instance template is found.
166ObjectTemplateInfo* GetParent(ObjectTemplateInfo* data) {
167 Object* maybe_ctor = data->constructor();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100168 Isolate* isolate = data->GetIsolate();
169 if (maybe_ctor->IsUndefined(isolate)) return nullptr;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100170 FunctionTemplateInfo* ctor = FunctionTemplateInfo::cast(maybe_ctor);
171 while (true) {
172 ctor = GetParent(ctor);
173 if (ctor == nullptr) return nullptr;
174 Object* maybe_obj = ctor->instance_template();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100175 if (!maybe_obj->IsUndefined(isolate)) {
176 return ObjectTemplateInfo::cast(maybe_obj);
177 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100178 }
179}
180
181template <typename TemplateInfoT>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100183 Handle<TemplateInfoT> data,
184 bool is_hidden_prototype) {
185 HandleScope scope(isolate);
186 // Disable access checks while instantiating the object.
187 AccessCheckDisableScope access_check_scope(isolate, obj);
188
189 // Walk the inheritance chain and copy all accessors to current object.
190 int max_number_of_properties = 0;
191 TemplateInfoT* info = *data;
192 while (info != nullptr) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100193 if (!info->property_accessors()->IsUndefined(isolate)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100194 Object* props = info->property_accessors();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100195 if (!props->IsUndefined(isolate)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100196 Handle<Object> props_handle(props, isolate);
197 NeanderArray props_array(props_handle);
198 max_number_of_properties += props_array.length();
199 }
200 }
201 info = GetParent(info);
202 }
203
204 if (max_number_of_properties > 0) {
205 int valid_descriptors = 0;
206 // Use a temporary FixedArray to accumulate unique accessors.
207 Handle<FixedArray> array =
208 isolate->factory()->NewFixedArray(max_number_of_properties);
209
210 info = *data;
211 while (info != nullptr) {
212 // Accumulate accessors.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100213 if (!info->property_accessors()->IsUndefined(isolate)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100214 Handle<Object> props(info->property_accessors(), isolate);
215 valid_descriptors =
216 AccessorInfo::AppendUnique(props, array, valid_descriptors);
217 }
218 info = GetParent(info);
219 }
220
221 // Install accumulated accessors.
222 for (int i = 0; i < valid_descriptors; i++) {
223 Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
224 JSObject::SetAccessor(obj, accessor).Assert();
225 }
226 }
227
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 auto property_list = handle(data->property_list(), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100229 if (property_list->IsUndefined(isolate)) return obj;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 // TODO(dcarney): just use a FixedArray here.
231 NeanderArray properties(property_list);
232 if (properties.length() == 0) return obj;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233
234 int i = 0;
235 for (int c = 0; c < data->number_of_properties(); c++) {
236 auto name = handle(Name::cast(properties.get(i++)), isolate);
237 auto bit = handle(properties.get(i++), isolate);
238 if (bit->IsSmi()) {
239 PropertyDetails details(Smi::cast(*bit));
240 PropertyAttributes attributes = details.attributes();
241 PropertyKind kind = details.kind();
242
243 if (kind == kData) {
244 auto prop_data = handle(properties.get(i++), isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245 RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
246 prop_data, attributes),
247 JSObject);
248 } else {
249 auto getter = handle(properties.get(i++), isolate);
250 auto setter = handle(properties.get(i++), isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100251 RETURN_ON_EXCEPTION(
252 isolate, DefineAccessorProperty(isolate, obj, name, getter, setter,
253 attributes, is_hidden_prototype),
254 JSObject);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255 }
256 } else {
257 // Intrinsic data property --- Get appropriate value from the current
258 // context.
259 PropertyDetails details(Smi::cast(properties.get(i++)));
260 PropertyAttributes attributes = details.attributes();
261 DCHECK_EQ(kData, details.kind());
262
263 v8::Intrinsic intrinsic =
264 static_cast<v8::Intrinsic>(Smi::cast(properties.get(i++))->value());
265 auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate);
266
267 RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
268 prop_data, attributes),
269 JSObject);
270 }
271 }
272 return obj;
273}
274
Ben Murdochda12d292016-06-02 14:46:10 +0100275void CacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100276 Handle<JSObject> object) {
277 auto cache = isolate->template_instantiations_cache();
Ben Murdochda12d292016-06-02 14:46:10 +0100278 auto new_cache =
279 UnseededNumberDictionary::AtNumberPut(cache, serial_number, object);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100280 isolate->native_context()->set_template_instantiations_cache(*new_cache);
281}
282
Ben Murdochda12d292016-06-02 14:46:10 +0100283void UncacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100284 auto cache = isolate->template_instantiations_cache();
Ben Murdochda12d292016-06-02 14:46:10 +0100285 int entry = cache->FindEntry(serial_number);
286 DCHECK(entry != UnseededNumberDictionary::kNotFound);
287 Handle<Object> result =
288 UnseededNumberDictionary::DeleteProperty(cache, entry);
289 USE(result);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100290 DCHECK(result->IsTrue(isolate));
Ben Murdochda12d292016-06-02 14:46:10 +0100291 auto new_cache = UnseededNumberDictionary::Shrink(cache, entry);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100292 isolate->native_context()->set_template_instantiations_cache(*new_cache);
293}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294
295MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100296 Handle<ObjectTemplateInfo> info,
Ben Murdochc5610432016-08-08 18:44:38 +0100297 Handle<JSReceiver> new_target,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100298 bool is_hidden_prototype) {
Ben Murdochc5610432016-08-08 18:44:38 +0100299 Handle<JSFunction> constructor;
Ben Murdochda12d292016-06-02 14:46:10 +0100300 uint32_t serial_number =
301 static_cast<uint32_t>(Smi::cast(info->serial_number())->value());
Ben Murdochc5610432016-08-08 18:44:38 +0100302 if (!new_target.is_null()) {
303 if (new_target->IsJSFunction() &&
304 JSFunction::cast(*new_target)->shared()->function_data() ==
305 info->constructor() &&
306 JSFunction::cast(*new_target)->context()->native_context() ==
307 isolate->context()->native_context()) {
308 constructor = Handle<JSFunction>::cast(new_target);
309 } else {
310 // Disable caching for subclass instantiation.
311 serial_number = 0;
312 }
313 }
314 // Fast path.
315 Handle<JSObject> result;
Ben Murdochda12d292016-06-02 14:46:10 +0100316 if (serial_number) {
317 // Probe cache.
318 auto cache = isolate->template_instantiations_cache();
319 int entry = cache->FindEntry(serial_number);
320 if (entry != UnseededNumberDictionary::kNotFound) {
321 Object* boilerplate = cache->ValueAt(entry);
322 result = handle(JSObject::cast(boilerplate), isolate);
323 return isolate->factory()->CopyJSObject(result);
324 }
325 }
326 // Enter a new scope. Recursion could otherwise create a lot of handles.
327 HandleScope scope(isolate);
Ben Murdochc5610432016-08-08 18:44:38 +0100328
329 if (constructor.is_null()) {
330 Handle<Object> cons(info->constructor(), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100331 if (cons->IsUndefined(isolate)) {
Ben Murdochc5610432016-08-08 18:44:38 +0100332 constructor = isolate->object_function();
333 } else {
334 auto cons_templ = Handle<FunctionTemplateInfo>::cast(cons);
335 ASSIGN_RETURN_ON_EXCEPTION(isolate, constructor,
336 InstantiateFunction(isolate, cons_templ),
337 JSObject);
338 }
339
340 if (new_target.is_null()) new_target = constructor;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 }
Ben Murdochc5610432016-08-08 18:44:38 +0100342
343 Handle<JSObject> object;
344 ASSIGN_RETURN_ON_EXCEPTION(isolate, object,
345 JSObject::New(constructor, new_target), JSObject);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100347 isolate, result,
Ben Murdochc5610432016-08-08 18:44:38 +0100348 ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349 // TODO(dcarney): is this necessary?
350 JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100351
Ben Murdochda12d292016-06-02 14:46:10 +0100352 if (serial_number) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100353 CacheTemplateInstantiation(isolate, serial_number, result);
Ben Murdochda12d292016-06-02 14:46:10 +0100354 result = isolate->factory()->CopyJSObject(result);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100355 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356 return scope.CloseAndEscape(result);
357}
358
359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
361 Handle<FunctionTemplateInfo> data,
362 Handle<Name> name) {
Ben Murdochda12d292016-06-02 14:46:10 +0100363 uint32_t serial_number =
364 static_cast<uint32_t>(Smi::cast(data->serial_number())->value());
365 if (serial_number) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100366 // Probe cache.
367 auto cache = isolate->template_instantiations_cache();
Ben Murdochda12d292016-06-02 14:46:10 +0100368 int entry = cache->FindEntry(serial_number);
369 if (entry != UnseededNumberDictionary::kNotFound) {
370 Object* element = cache->ValueAt(entry);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371 return handle(JSFunction::cast(element), isolate);
372 }
373 }
374 // Enter a new scope. Recursion could otherwise create a lot of handles.
375 HandleScope scope(isolate);
376 Handle<JSObject> prototype;
377 if (!data->remove_prototype()) {
378 auto prototype_templ = handle(data->prototype_template(), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100379 if (prototype_templ->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000380 prototype = isolate->factory()->NewJSObject(isolate->object_function());
381 } else {
382 ASSIGN_RETURN_ON_EXCEPTION(
383 isolate, prototype,
384 InstantiateObject(isolate,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100385 Handle<ObjectTemplateInfo>::cast(prototype_templ),
Ben Murdochc5610432016-08-08 18:44:38 +0100386 Handle<JSReceiver>(), data->hidden_prototype()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000387 JSFunction);
388 }
389 auto parent = handle(data->parent_template(), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100390 if (!parent->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000391 Handle<JSFunction> parent_instance;
392 ASSIGN_RETURN_ON_EXCEPTION(
393 isolate, parent_instance,
394 InstantiateFunction(isolate,
395 Handle<FunctionTemplateInfo>::cast(parent)),
396 JSFunction);
397 // TODO(dcarney): decide what to do here.
398 Handle<Object> parent_prototype;
399 ASSIGN_RETURN_ON_EXCEPTION(
400 isolate, parent_prototype,
401 JSObject::GetProperty(parent_instance,
402 isolate->factory()->prototype_string()),
403 JSFunction);
404 MAYBE_RETURN(JSObject::SetPrototype(prototype, parent_prototype, false,
405 Object::THROW_ON_ERROR),
406 MaybeHandle<JSFunction>());
407 }
408 }
409 auto function = ApiNatives::CreateApiFunction(
410 isolate, data, prototype, ApiNatives::JavaScriptObjectType);
411 if (!name.is_null() && name->IsString()) {
412 function->shared()->set_name(*name);
413 }
Ben Murdochda12d292016-06-02 14:46:10 +0100414 if (serial_number) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000415 // Cache the function.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100416 CacheTemplateInstantiation(isolate, serial_number, function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000417 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100418 auto result =
419 ConfigureInstance(isolate, function, data, data->hidden_prototype());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420 if (result.is_null()) {
421 // Uncache on error.
Ben Murdochda12d292016-06-02 14:46:10 +0100422 if (serial_number) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100423 UncacheTemplateInstantiation(isolate, serial_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000424 }
425 return MaybeHandle<JSFunction>();
426 }
427 return scope.CloseAndEscape(function);
428}
429
430
431class InvokeScope {
432 public:
433 explicit InvokeScope(Isolate* isolate)
434 : isolate_(isolate), save_context_(isolate) {}
435 ~InvokeScope() {
436 bool has_exception = isolate_->has_pending_exception();
437 if (has_exception) {
438 isolate_->ReportPendingMessages();
439 } else {
440 isolate_->clear_pending_message();
441 }
442 }
443
444 private:
445 Isolate* isolate_;
446 SaveContext save_context_;
447};
448
449
450void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ,
451 int length, Handle<Object>* data) {
452 auto list = handle(templ->property_list(), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100453 if (list->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454 list = NeanderArray(isolate).value();
455 templ->set_property_list(*list);
456 }
457 templ->set_number_of_properties(templ->number_of_properties() + 1);
458 NeanderArray array(list);
459 for (int i = 0; i < length; i++) {
460 Handle<Object> value =
461 data[i].is_null()
462 ? Handle<Object>::cast(isolate->factory()->undefined_value())
463 : data[i];
464 array.add(isolate, value);
465 }
466}
467
468} // namespace
469
470
471MaybeHandle<JSFunction> ApiNatives::InstantiateFunction(
472 Handle<FunctionTemplateInfo> data) {
473 Isolate* isolate = data->GetIsolate();
474 InvokeScope invoke_scope(isolate);
475 return ::v8::internal::InstantiateFunction(isolate, data);
476}
477
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478MaybeHandle<JSObject> ApiNatives::InstantiateObject(
Ben Murdochc5610432016-08-08 18:44:38 +0100479 Handle<ObjectTemplateInfo> data, Handle<JSReceiver> new_target) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480 Isolate* isolate = data->GetIsolate();
481 InvokeScope invoke_scope(isolate);
Ben Murdochc5610432016-08-08 18:44:38 +0100482 return ::v8::internal::InstantiateObject(isolate, data, new_target, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483}
484
485
486void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
487 Handle<Name> name, Handle<Object> value,
488 PropertyAttributes attributes) {
489 const int kSize = 3;
490 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
491 auto details_handle = handle(details.AsSmi(), isolate);
492 Handle<Object> data[kSize] = {name, details_handle, value};
493 AddPropertyToPropertyList(isolate, info, kSize, data);
494}
495
496
497void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
498 Handle<Name> name, v8::Intrinsic intrinsic,
499 PropertyAttributes attributes) {
500 const int kSize = 4;
501 auto value = handle(Smi::FromInt(intrinsic), isolate);
502 auto intrinsic_marker = isolate->factory()->true_value();
503 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
504 auto details_handle = handle(details.AsSmi(), isolate);
505 Handle<Object> data[kSize] = {name, intrinsic_marker, details_handle, value};
506 AddPropertyToPropertyList(isolate, info, kSize, data);
507}
508
509
510void ApiNatives::AddAccessorProperty(Isolate* isolate,
511 Handle<TemplateInfo> info,
512 Handle<Name> name,
513 Handle<FunctionTemplateInfo> getter,
514 Handle<FunctionTemplateInfo> setter,
515 PropertyAttributes attributes) {
516 const int kSize = 4;
517 PropertyDetails details(attributes, ACCESSOR, 0, PropertyCellType::kNoCell);
518 auto details_handle = handle(details.AsSmi(), isolate);
519 Handle<Object> data[kSize] = {name, details_handle, getter, setter};
520 AddPropertyToPropertyList(isolate, info, kSize, data);
521}
522
523
524void ApiNatives::AddNativeDataProperty(Isolate* isolate,
525 Handle<TemplateInfo> info,
526 Handle<AccessorInfo> property) {
527 auto list = handle(info->property_accessors(), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100528 if (list->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 list = NeanderArray(isolate).value();
530 info->set_property_accessors(*list);
531 }
532 NeanderArray array(list);
533 array.add(isolate, property);
534}
535
536
537Handle<JSFunction> ApiNatives::CreateApiFunction(
538 Isolate* isolate, Handle<FunctionTemplateInfo> obj,
539 Handle<Object> prototype, ApiInstanceType instance_type) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100540 Handle<SharedFunctionInfo> shared =
541 FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj);
542 Handle<JSFunction> result =
543 isolate->factory()->NewFunctionFromSharedFunctionInfo(
544 shared, isolate->native_context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000545
546 if (obj->remove_prototype()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100547 result->set_map(*isolate->sloppy_function_without_prototype_map());
548 DCHECK(prototype.is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 DCHECK(result->shared()->IsApiFunction());
550 DCHECK(!result->has_initial_map());
551 DCHECK(!result->has_prototype());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100552 DCHECK(!result->IsConstructor());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000553 return result;
554 }
555
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000556 // Down from here is only valid for API functions that can be used as a
557 // constructor (don't set the "remove prototype" flag).
558
Ben Murdoch61f157c2016-09-16 13:49:30 +0100559 if (obj->read_only_prototype()) {
560 result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
561 }
562
563 if (prototype->IsTheHole(isolate)) {
564 prototype = isolate->factory()->NewFunctionPrototype(result);
565 } else {
566 JSObject::AddProperty(Handle<JSObject>::cast(prototype),
567 isolate->factory()->constructor_string(), result,
568 DONT_ENUM);
569 }
570
571 int internal_field_count = 0;
572 if (!obj->instance_template()->IsUndefined(isolate)) {
573 Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>(
574 ObjectTemplateInfo::cast(obj->instance_template()));
575 internal_field_count =
576 Smi::cast(instance_template->internal_field_count())->value();
577 }
578
579 // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing
580 // JSObject::GetHeaderSize.
581 int instance_size = kPointerSize * internal_field_count;
582 InstanceType type;
583 switch (instance_type) {
584 case JavaScriptObjectType:
585 if (!obj->needs_access_check() &&
586 obj->named_property_handler()->IsUndefined(isolate) &&
587 obj->indexed_property_handler()->IsUndefined(isolate)) {
588 type = JS_API_OBJECT_TYPE;
589 } else {
590 type = JS_SPECIAL_API_OBJECT_TYPE;
591 }
592 instance_size += JSObject::kHeaderSize;
593 break;
594 case GlobalObjectType:
595 type = JS_GLOBAL_OBJECT_TYPE;
596 instance_size += JSGlobalObject::kSize;
597 break;
598 case GlobalProxyType:
599 type = JS_GLOBAL_PROXY_TYPE;
600 instance_size += JSGlobalProxy::kSize;
601 break;
602 default:
603 UNREACHABLE();
604 type = JS_OBJECT_TYPE; // Keep the compiler happy.
605 break;
606 }
607
608 Handle<Map> map =
609 isolate->factory()->NewMap(type, instance_size, FAST_HOLEY_SMI_ELEMENTS);
610 JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000611
612 // Mark as undetectable if needed.
613 if (obj->undetectable()) {
614 map->set_is_undetectable();
615 }
616
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000617 // Mark as needs_access_check if needed.
618 if (obj->needs_access_check()) {
619 map->set_is_access_check_needed(true);
620 }
621
622 // Set interceptor information in the map.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100623 if (!obj->named_property_handler()->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624 map->set_has_named_interceptor();
625 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100626 if (!obj->indexed_property_handler()->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627 map->set_has_indexed_interceptor();
628 }
629
630 // Mark instance as callable in the map.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100631 if (!obj->instance_call_handler()->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000632 map->set_is_callable();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100633 map->set_is_constructor(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000634 }
635
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000636 return result;
637}
638
639} // namespace internal
640} // namespace v8