-
-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathArrayAdapter.mm
More file actions
131 lines (119 loc) · 3.63 KB
/
Copy pathArrayAdapter.mm
File metadata and controls
131 lines (119 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "ArrayAdapter.h"
#include "ArgConverter.h"
#include "DataWrapper.h"
#include "Helpers.h"
#include "Interop.h"
#include "IsolateWrapper.h"
using namespace tns;
using namespace v8;
@implementation ArrayAdapter {
IsolateWrapper* wrapper_;
std::shared_ptr<Persistent<Value>> object_;
// we're responsible for this wrapper
ObjCDataWrapper* dataWrapper_;
}
- (instancetype)initWithJSObject:(Local<Object>)jsObject isolate:(Isolate*)isolate {
if (self) {
self->wrapper_ = new IsolateWrapper(isolate);
self->object_ = std::make_shared<Persistent<Value>>(isolate, jsObject);
self->wrapper_->GetCache()->Instances.emplace(self, self->object_);
tns::SetValue(isolate, jsObject, (self->dataWrapper_ = new ObjCDataWrapper(self)));
}
return self;
}
- (NSUInteger)count {
auto isolate = wrapper_->Isolate();
if (!wrapper_->IsValid()) {
return 0;
}
NSUInteger result = 0;
// Scopes-before-@throw: a branded escape from the JS boundary is @thrown only
// after the inner block's V8 scopes destruct.
NSException* __strong pendingThrow = nil;
{
v8::Locker locker(isolate);
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<Object> object = self->object_->Get(isolate).As<Object>();
if (object->IsArray()) {
result = object.As<v8::Array>()->Length();
} else {
Local<Context> context = wrapper_->GetCache()->GetContext();
Local<v8::Array> propertyNames;
TryCatch tc(isolate);
if (object->GetPropertyNames(context).ToLocal(&propertyNames)) {
result = propertyNames->Length();
} else {
NSException* ex = ArgConverter::HandleBoundaryException(context, tc);
if (ex != nil) {
pendingThrow = ex;
}
}
}
}
if (pendingThrow != nil) {
@throw pendingThrow;
}
return result;
}
- (id)objectAtIndex:(NSUInteger)index {
auto isolate = wrapper_->Isolate();
if (!wrapper_->IsValid()) {
return nil;
}
if (!(index < [self count])) {
// Out of bounds: return the adapter default rather than aborting.
return nil;
}
id result = nil;
NSException* __strong pendingThrow = nil;
{
v8::Locker locker(isolate);
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<Object> object = self->object_->Get(isolate).As<Object>();
Local<Context> context = wrapper_->GetCache()->GetContext();
Local<Value> item;
TryCatch tc(isolate);
if (!object->Get(context, (uint)index).ToLocal(&item)) {
NSException* ex = ArgConverter::HandleBoundaryException(context, tc);
if (ex != nil) {
pendingThrow = ex;
}
} else if (!item->IsNullOrUndefined()) {
result = Interop::ToObject(context, item);
}
}
if (pendingThrow != nil) {
@throw pendingThrow;
}
return result;
}
- (void)dealloc {
if (wrapper_->IsValid()) {
auto isolate = wrapper_->Isolate();
v8::Locker locker(isolate);
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
wrapper_->GetCache()->Instances.erase(self);
Local<Value> value = self->object_->Get(isolate);
BaseDataWrapper* wrapper = tns::GetValue(isolate, value);
if (wrapper != nullptr) {
tns::DeleteValue(isolate, value);
// ensure we don't delete the same wrapper twice
// this is just needed as a failsafe in case some other wrapper is assigned to this object
if (wrapper == dataWrapper_) {
dataWrapper_ = nullptr;
}
delete wrapper;
}
self->object_->Reset();
}
delete wrapper_;
if (dataWrapper_ != nullptr) {
delete dataWrapper_;
}
self->object_ = nullptr;
[super dealloc];
}
@end