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;
7375using v8::Local;
7476using v8::Number;
7577using v8::Object;
78+ using v8::Persistent;
7679using v8::String;
7780using v8::Uint32;
7881using v8::Uint8Array;
7982using 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+
82175bool 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) {
277370Local<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,
289382Local<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
0 commit comments