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