1414
1515static struct zjs_buffer_t * zjs_buffers = NULL ;
1616
17- struct zjs_buffer_t * zjs_find_buffer (const jerry_object_t * obj )
17+ // TODO: this could probably be replaced more efficiently now that there is a
18+ // get_native_handle API
19+ struct zjs_buffer_t * zjs_buffer_find (const jerry_object_t * obj )
1820{
1921 // requires: obj should be the JS object associated with a buffer, created
2022 // in zjs_buffer
@@ -26,13 +28,51 @@ struct zjs_buffer_t *zjs_find_buffer(const jerry_object_t *obj)
2628 return NULL ;
2729}
2830
31+ static bool zjs_buffer_read_uint8 (const jerry_object_t * function_obj_p ,
32+ const jerry_value_t this_val ,
33+ const jerry_value_t args_p [],
34+ const jerry_length_t args_cnt ,
35+ jerry_value_t * ret_val_p )
36+ {
37+ // requires: this_val is a JS buffer object created with zjs_buffer_create,
38+ // expects argument of an offset into the buffer, but will
39+ // treat offset as 0 if not given, as node.js seems to
40+ // effects: reads single byte value from the buffer associated with the
41+ // this_p JS object, if found, at the given offset, if within
42+ // the bounds of the buffer; otherwise returns an error
43+ if (args_cnt >= 1 && !jerry_value_is_number (args_p [0 ])) {
44+ PRINT ("Unsupported argument to readUInt8\n" );
45+ return false;
46+ }
47+
48+ uint32_t offset = 0 ;
49+ if (args_cnt > 1 )
50+ offset = (uint32_t )jerry_get_number_value (args_p [0 ]);
51+
52+ jerry_object_t * obj = jerry_get_object_value (this_val );
53+ struct zjs_buffer_t * buf = zjs_buffer_find (obj );
54+ if (buf ) {
55+ if (offset >= buf -> bufsize ) {
56+ PRINT ("Tried to read beyond end of buffer\n" );
57+ return false;
58+ }
59+ uint8_t value = buf -> buffer [offset ];
60+
61+ * ret_val_p = jerry_create_number_value (value );
62+ return true;
63+ }
64+
65+ PRINT ("Read called on a buffer not in list" ); // Fatal
66+ return false;
67+ }
68+
2969static bool zjs_buffer_write_uint8 (const jerry_object_t * function_obj_p ,
3070 const jerry_value_t this_val ,
3171 const jerry_value_t args_p [],
3272 const jerry_length_t args_cnt ,
3373 jerry_value_t * ret_val_p )
3474{
35- // requires: this_val is a JS buffer object created with zjs_buffer ,
75+ // requires: this_val is a JS buffer object created with zjs_buffer_create ,
3676 // expects arguments of the value to write and an offset
3777 // into the buffer, but will treat offset as 0 if not given,
3878 // as node.js seems to
@@ -52,17 +92,19 @@ static bool zjs_buffer_write_uint8(const jerry_object_t *function_obj_p,
5292 offset = (uint32_t )jerry_get_number_value (args_p [1 ]);
5393
5494 jerry_object_t * obj = jerry_get_object_value (this_val );
55- struct zjs_buffer_t * buf = zjs_find_buffer (obj );
95+ struct zjs_buffer_t * buf = zjs_buffer_find (obj );
5696 if (buf ) {
5797 if (offset >= buf -> bufsize ) {
5898 PRINT ("Tried to write beyond end of buffer\n" );
5999 return false;
60100 }
61- (( char * ) buf -> buffer ) [offset ] = value ;
101+ buf -> buffer [offset ] = value ;
62102
63103 * ret_val_p = jerry_create_number_value (offset + 1 );
64104 return true;
65105 }
106+
107+ PRINT ("Write called on a buffer not in list" ); // Fatal
66108 return false;
67109}
68110
@@ -91,7 +133,7 @@ static bool zjs_buffer_to_string(const jerry_object_t *function_obj_p,
91133 }
92134
93135 jerry_object_t * obj = jerry_get_object_value (this_val );
94- struct zjs_buffer_t * buf = zjs_find_buffer (obj );
136+ struct zjs_buffer_t * buf = zjs_buffer_find (obj );
95137 if (buf && args_cnt == 0 ) {
96138 * ret_val_p = jerry_create_string_value (jerry_create_string (
97139 (jerry_char_t * )"[Buffer Object]" ));
@@ -127,25 +169,28 @@ static bool zjs_buffer_to_string(const jerry_object_t *function_obj_p,
127169 return false;
128170}
129171
130- // Buffer constructor
131- static bool zjs_buffer (const jerry_object_t * function_obj_p ,
132- const jerry_value_t this_val ,
133- const jerry_value_t args_p [],
134- const jerry_length_t args_cnt ,
135- jerry_value_t * ret_val_p )
172+ static void zjs_buffer_callback_free (uintptr_t handle )
136173{
137- // requires: single argument is a numeric size in bytes; soon will also
138- // support an array argument to initialize the buffer
139- // effects: constructs a new JS Buffer object, and an associated buffer
140- // tied to it through a zjs_buffer_t struct stored in a global
141- // list
142- if (args_cnt != 1 || !jerry_value_is_number (args_p [0 ])) {
143- PRINT ("Unsupported arguments to Buffer constructor\n" );
144- return false;
174+ // requires: handle is the native pointer we registered with
175+ // jerry_set_object_native_handle
176+ // effects: frees the callback list item for the given pin object
177+ struct zjs_buffer_t * * pItem = & zjs_buffers ;
178+ while (* pItem ) {
179+ if ((uintptr_t )* pItem == handle ) {
180+ task_free ((* pItem )-> buffer );
181+ * pItem = (* pItem )-> next ;
182+ task_free ((void * )handle );
183+ }
184+ pItem = & (* pItem )-> next ;
145185 }
186+ }
146187
147- uint32_t size = (uint32_t )jerry_get_number_value (args_p [0 ]);
148-
188+ jerry_object_t * zjs_buffer_create (uint32_t size )
189+ {
190+ // requires: size is size of desired buffer, in bytes
191+ // effects: allocates a JS Buffer object, an underlying C buffer, and a
192+ // list item to track it; if any of these fail, free them all
193+ // and return NULL, otherwise return the JS object
149194 jerry_object_t * buf_obj = jerry_create_object ();
150195 void * buf = task_malloc (size );
151196 struct zjs_buffer_t * buf_item =
@@ -156,7 +201,7 @@ static bool zjs_buffer(const jerry_object_t *function_obj_p,
156201 jerry_release_object (buf_obj );
157202 task_free (buf );
158203 task_free (buf_item );
159- return false ;
204+ return NULL ;
160205 }
161206
162207 buf_item -> obj = buf_obj ;
@@ -165,13 +210,46 @@ static bool zjs_buffer(const jerry_object_t *function_obj_p,
165210 buf_item -> next = zjs_buffers ;
166211 zjs_buffers = buf_item ;
167212
213+ zjs_obj_add_uint32 (buf_obj , size , "length" );
214+ zjs_obj_add_function (buf_obj , zjs_buffer_read_uint8 , "readUInt8" );
168215 zjs_obj_add_function (buf_obj , zjs_buffer_write_uint8 , "writeUInt8" );
169216 zjs_obj_add_function (buf_obj , zjs_buffer_to_string , "toString" );
170217
171- zjs_init_value_object (ret_val_p , buf_obj );
172-
173218 // TODO: sign up to get callback when the object is freed, then free the
174219 // buffer and remove it from the list
220+
221+ // watch for the object getting garbage collected, and clean up
222+ jerry_set_object_native_handle (buf_obj , (uintptr_t )buf_item ,
223+ zjs_buffer_callback_free );
224+
225+ return buf_obj ;
226+ }
227+
228+ // Buffer constructor
229+ static bool zjs_buffer (const jerry_object_t * function_obj_p ,
230+ const jerry_value_t this_val ,
231+ const jerry_value_t args_p [],
232+ const jerry_length_t args_cnt ,
233+ jerry_value_t * ret_val_p )
234+ {
235+ // requires: single argument is a numeric size in bytes; soon will also
236+ // support an array argument to initialize the buffer
237+ // effects: constructs a new JS Buffer object, and an associated buffer
238+ // tied to it through a zjs_buffer_t struct stored in a global
239+ // list
240+ if (args_cnt != 1 || !jerry_value_is_number (args_p [0 ])) {
241+ PRINT ("Unsupported arguments to Buffer constructor\n" );
242+ return false;
243+ }
244+
245+ uint32_t size = (uint32_t )jerry_get_number_value (args_p [0 ]);
246+
247+ jerry_object_t * buf_obj = zjs_buffer_create (size );
248+ if (!buf_obj )
249+ return false;
250+
251+ * ret_val_p = jerry_create_object_value (buf_obj );
252+
175253 return true;
176254}
177255
0 commit comments