Skip to content

Commit d75f5c8

Browse files
trevnorrisrvagg
authored andcommitted
buffer: finish implementing FreeCallback
Passing a FreeCallback to Buffer::New() now uses externalized ArrayBuffer's. PR-URL: #1825 Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 63da0df commit d75f5c8

File tree

2 files changed

+116
-12
lines changed

2 files changed

+116
-12
lines changed

src/node_buffer.cc

+111-9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <string.h>
1414
#include <limits.h>
1515

16+
#define BUFFER_ID 0xB0E4
17+
1618
#define MIN(a, b) ((a) < (b) ? (a) : (b))
1719

1820
#define CHECK_NOT_OOB(r) \
@@ -73,12 +75,103 @@ using v8::Isolate;
7375
using v8::Local;
7476
using v8::Number;
7577
using v8::Object;
78+
using v8::Persistent;
7679
using v8::String;
7780
using v8::Uint32;
7881
using v8::Uint8Array;
7982
using v8::Value;
83+
using v8::WeakCallbackData;
84+
85+
86+
class CallbackInfo {
87+
public:
88+
static inline void Free(char* data, void* hint);
89+
static inline CallbackInfo* New(Isolate* isolate,
90+
Handle<Object> object,
91+
FreeCallback callback,
92+
void* hint = 0);
93+
inline void Dispose(Isolate* isolate);
94+
inline Persistent<Object>* persistent();
95+
private:
96+
static void WeakCallback(const WeakCallbackData<Object, CallbackInfo>&);
97+
inline void WeakCallback(Isolate* isolate, Local<Object> object);
98+
inline CallbackInfo(Isolate* isolate,
99+
Handle<Object> object,
100+
FreeCallback callback,
101+
void* hint);
102+
~CallbackInfo();
103+
Persistent<Object> persistent_;
104+
FreeCallback const callback_;
105+
void* const hint_;
106+
DISALLOW_COPY_AND_ASSIGN(CallbackInfo);
107+
};
108+
109+
110+
void CallbackInfo::Free(char* data, void*) {
111+
::free(data);
112+
}
113+
114+
115+
CallbackInfo* CallbackInfo::New(Isolate* isolate,
116+
Handle<Object> object,
117+
FreeCallback callback,
118+
void* hint) {
119+
return new CallbackInfo(isolate, object, callback, hint);
120+
}
121+
122+
123+
void CallbackInfo::Dispose(Isolate* isolate) {
124+
WeakCallback(isolate, PersistentToLocal(isolate, persistent_));
125+
}
126+
127+
128+
Persistent<Object>* CallbackInfo::persistent() {
129+
return &persistent_;
130+
}
131+
132+
133+
CallbackInfo::CallbackInfo(Isolate* isolate,
134+
Handle<Object> object,
135+
FreeCallback callback,
136+
void* hint)
137+
: persistent_(isolate, object),
138+
callback_(callback),
139+
hint_(hint) {
140+
persistent_.SetWeak(this, WeakCallback);
141+
persistent_.SetWrapperClassId(BUFFER_ID);
142+
persistent_.MarkIndependent();
143+
isolate->AdjustAmountOfExternalAllocatedMemory(sizeof(*this));
144+
}
145+
146+
147+
CallbackInfo::~CallbackInfo() {
148+
persistent_.Reset();
149+
}
150+
151+
152+
void CallbackInfo::WeakCallback(
153+
const WeakCallbackData<Object, CallbackInfo>& data) {
154+
data.GetParameter()->WeakCallback(data.GetIsolate(), data.GetValue());
155+
}
80156

81157

158+
void CallbackInfo::WeakCallback(Isolate* isolate, Local<Object> object) {
159+
ARGS_THIS_DEC(obj);
160+
SPREAD_ARG(object, obj);
161+
CHECK_EQ(obj_offset, 0);
162+
CHECK_EQ(obj_c.ByteLength(), obj_length);
163+
164+
obj->Buffer()->Neuter();
165+
callback_(obj_data, hint_);
166+
int64_t change_in_bytes = -static_cast<int64_t>(sizeof(*this));
167+
isolate->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
168+
169+
delete this;
170+
}
171+
172+
173+
// Buffer methods
174+
82175
bool HasInstance(Handle<Value> val) {
83176
return val->IsObject() && HasInstance(val.As<Object>());
84177
}
@@ -277,7 +370,7 @@ Local<Object> New(Environment* env, const char* data, size_t length) {
277370
Local<Object> New(Isolate* isolate,
278371
char* data,
279372
size_t length,
280-
smalloc::FreeCallback callback,
373+
FreeCallback callback,
281374
void* hint) {
282375
Environment* env = Environment::GetCurrent(isolate);
283376
EscapableHandleScope handle_scope(env->isolate());
@@ -289,19 +382,28 @@ Local<Object> New(Isolate* isolate,
289382
Local<Object> New(Environment* env,
290383
char* data,
291384
size_t length,
292-
smalloc::FreeCallback callback,
385+
FreeCallback callback,
293386
void* hint) {
294387
EscapableHandleScope scope(env->isolate());
295388

296-
// TODO(trevnorris): IMPLEMENT
297-
CHECK_LE(length, kMaxLength);
298-
299-
Local<Value> arg = Uint32::NewFromUnsigned(env->isolate(), length);
300-
Local<Object> obj = env->buffer_constructor_function()->NewInstance(1, &arg);
389+
if (using_old_buffer) {
390+
CHECK_LE(length, kMaxLength);
391+
Local<Value> arg = Uint32::NewFromUnsigned(env->isolate(), length);
392+
Local<Object> obj =
393+
env->buffer_constructor_function()->NewInstance(1, &arg);
394+
smalloc::Alloc(env, obj, data, length, callback, hint);
395+
return scope.Escape(obj);
396+
}
301397

302-
smalloc::Alloc(env, obj, data, length, callback, hint);
398+
if (!IsValidSmi(length)) {
399+
return Local<Object>();
400+
}
303401

304-
return scope.Escape(obj);
402+
Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), data, length);
403+
Local<Uint8Array> ui = Uint8Array::New(ab, 0, length);
404+
ui->SetPrototype(env->buffer_prototype_object());
405+
CallbackInfo::New(env->isolate(), ui, callback, hint);
406+
return scope.Escape(ui);
305407
}
306408

307409

src/node_buffer.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace Buffer {
1414

1515
static const unsigned int kMaxLength = smalloc::kMaxLength;
1616

17+
NODE_EXTERN typedef void (*FreeCallback)(char* data, void* hint);
18+
1719
NODE_EXTERN bool HasInstance(v8::Handle<v8::Value> val);
1820
NODE_EXTERN bool HasInstance(v8::Handle<v8::Object> val);
1921
NODE_EXTERN char* Data(v8::Handle<v8::Value> val);
@@ -49,12 +51,12 @@ NODE_DEPRECATED("Use New(isolate, ...)",
4951
NODE_EXTERN v8::Local<v8::Object> New(v8::Isolate* isolate,
5052
char* data,
5153
size_t length,
52-
smalloc::FreeCallback callback,
54+
FreeCallback callback,
5355
void* hint);
5456
NODE_DEPRECATED("Use New(isolate, ...)",
5557
inline v8::Local<v8::Object> New(char* data,
5658
size_t length,
57-
smalloc::FreeCallback callback,
59+
FreeCallback callback,
5860
void* hint) {
5961
return New(v8::Isolate::GetCurrent(), data, length, callback, hint);
6062
})
@@ -93,7 +95,7 @@ v8::Local<v8::Object> New(Environment* env, const char* data, size_t len);
9395
v8::Local<v8::Object> New(Environment* env,
9496
char* data,
9597
size_t length,
96-
smalloc::FreeCallback callback,
98+
FreeCallback callback,
9799
void* hint);
98100
v8::Local<v8::Object> Use(Environment* env, char* data, size_t length);
99101
#endif // defined(NODE_WANT_INTERNALS)

0 commit comments

Comments
 (0)