22// License, v. 2.0. If a copy of the MPL was not distributed with this
33// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44
5- use andromeda_core:: { Extension , ExtensionOp } ;
5+ use andromeda_core:: { Extension , ExtensionOp , HostData , OpsStorage } ;
66use nova_vm:: {
77 ecmascript:: {
88 builtins:: ArgumentsList ,
@@ -12,12 +12,9 @@ use nova_vm::{
1212 engine:: context:: { Bindable , GcScope } ,
1313} ;
1414use std:: collections:: HashMap ;
15- use std:: sync:: { Arc , Mutex } ;
1615use uuid:: Uuid ;
1716
18- // Resource table for managing blob data
19- static BLOB_STORAGE : std:: sync:: OnceLock < Arc < Mutex < HashMap < String , BlobData > > > > =
20- std:: sync:: OnceLock :: new ( ) ;
17+ use crate :: RuntimeMacroTask ;
2118
2219// Internal blob data structure
2320#[ derive( Clone ) ]
@@ -27,6 +24,11 @@ struct BlobData {
2724 size : usize ,
2825}
2926
27+ // Extension resources structure
28+ struct FileExtResources {
29+ blob_storage : HashMap < String , BlobData > ,
30+ }
31+
3032#[ derive( Default ) ]
3133pub struct FileExt ;
3234
@@ -86,7 +88,11 @@ impl FileExt {
8688 1 ,
8789 ) ,
8890 ] ,
89- storage : None ,
91+ storage : Some ( Box :: new ( |storage : & mut OpsStorage | {
92+ storage. insert ( FileExtResources {
93+ blob_storage : HashMap :: new ( ) ,
94+ } ) ;
95+ } ) ) ,
9096 files : vec ! [
9197 include_str!( "./blob.ts" ) ,
9298 include_str!( "./file.ts" ) ,
@@ -95,10 +101,13 @@ impl FileExt {
95101 }
96102 }
97103
98- fn get_blob_storage ( ) -> Arc < Mutex < HashMap < String , BlobData > > > {
99- BLOB_STORAGE
100- . get_or_init ( || Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) )
101- . clone ( )
104+ fn get_blob_storage_mut ( agent : & Agent ) -> std:: cell:: RefMut < ' _ , HashMap < String , BlobData > > {
105+ let host_data = agent. get_host_data ( ) ;
106+ let host_data: & HostData < RuntimeMacroTask > = host_data. downcast_ref ( ) . unwrap ( ) ;
107+ let storage = host_data. storage . borrow_mut ( ) ;
108+ std:: cell:: RefMut :: map ( storage, |s| {
109+ & mut s. get_mut :: < FileExtResources > ( ) . unwrap ( ) . blob_storage
110+ } )
102111 }
103112
104113 pub fn internal_blob_create < ' gc > (
@@ -146,8 +155,9 @@ impl FileExt {
146155 size,
147156 } ;
148157
149- let storage = Self :: get_blob_storage ( ) ;
150- storage. lock ( ) . unwrap ( ) . insert ( blob_id. clone ( ) , blob) ;
158+ let mut storage = Self :: get_blob_storage_mut ( agent) ;
159+ storage. insert ( blob_id. clone ( ) , blob) ;
160+ drop ( storage) ;
151161
152162 let gc_no = gc. into_nogc ( ) ;
153163 Ok ( Value :: from_string ( agent, blob_id, gc_no) . unbind ( ) )
@@ -189,24 +199,26 @@ impl FileExt {
189199 . to_string ( )
190200 } ;
191201
192- let storage = Self :: get_blob_storage ( ) ;
193- let storage_lock = storage. lock ( ) . unwrap ( ) ;
202+ let storage = Self :: get_blob_storage_mut ( agent) ;
203+
204+ if let Some ( blob) = storage. get ( blob_id) {
205+ let blob_clone = blob. clone ( ) ;
206+ drop ( storage) ;
194207
195- if let Some ( blob) = storage_lock. get ( blob_id) {
196208 let end = if end_arg. is_undefined ( ) {
197- blob . size
209+ blob_clone . size
198210 } else {
199211 ( end_arg
200212 . to_number ( agent, gc. reborrow ( ) )
201213 . unbind ( ) ?
202214 . into_f64 ( agent) as usize )
203- . min ( blob . size )
215+ . min ( blob_clone . size )
204216 } ;
205217
206- let start = start. min ( blob . size ) ;
218+ let start = start. min ( blob_clone . size ) ;
207219 let end = end. max ( start) ;
208220
209- let sliced_data = blob . data [ start..end] . to_vec ( ) ;
221+ let sliced_data = blob_clone . data [ start..end] . to_vec ( ) ;
210222 let new_blob_id = Uuid :: new_v4 ( ) . to_string ( ) ;
211223
212224 let new_blob = BlobData {
@@ -215,14 +227,13 @@ impl FileExt {
215227 size : end - start,
216228 } ;
217229
218- drop ( storage_lock) ;
219- storage
220- . lock ( )
221- . unwrap ( )
222- . insert ( new_blob_id. clone ( ) , new_blob) ;
230+ let mut storage = Self :: get_blob_storage_mut ( agent) ;
231+ storage. insert ( new_blob_id. clone ( ) , new_blob) ;
232+ drop ( storage) ;
223233
224234 Ok ( Value :: from_string ( agent, new_blob_id, gc. nogc ( ) ) . unbind ( ) )
225235 } else {
236+ drop ( storage) ;
226237 Err ( agent
227238 . throw_exception (
228239 ExceptionType :: Error ,
@@ -246,18 +257,19 @@ impl FileExt {
246257 . as_str ( agent)
247258 . expect ( "String is not valid UTF-8" ) ;
248259
249- let storage = Self :: get_blob_storage ( ) ;
250- let storage_lock = storage. lock ( ) . unwrap ( ) ;
260+ let storage = Self :: get_blob_storage_mut ( agent) ;
251261
252- if let Some ( blob) = storage_lock . get ( blob_id) {
262+ if let Some ( blob) = storage . get ( blob_id) {
253263 let bytes_str = blob
254264 . data
255265 . iter ( )
256266 . map ( |b| b. to_string ( ) )
257267 . collect :: < Vec < _ > > ( )
258268 . join ( "," ) ;
269+ drop ( storage) ;
259270 Ok ( Value :: from_string ( agent, bytes_str, gc. nogc ( ) ) . unbind ( ) )
260271 } else {
272+ drop ( storage) ;
261273 Err ( agent
262274 . throw_exception (
263275 ExceptionType :: Error ,
@@ -281,12 +293,14 @@ impl FileExt {
281293 . as_str ( agent)
282294 . expect ( "String is not valid UTF-8" ) ;
283295
284- let storage = Self :: get_blob_storage ( ) ;
285- let storage_lock = storage. lock ( ) . unwrap ( ) ;
296+ let storage = Self :: get_blob_storage_mut ( agent) ;
286297
287- if let Some ( blob) = storage_lock. get ( blob_id) {
288- Ok ( Value :: from_f64 ( agent, blob. size as f64 , gc. nogc ( ) ) . unbind ( ) )
298+ if let Some ( blob) = storage. get ( blob_id) {
299+ let size = blob. size ;
300+ drop ( storage) ;
301+ Ok ( Value :: from_f64 ( agent, size as f64 , gc. nogc ( ) ) . unbind ( ) )
289302 } else {
303+ drop ( storage) ;
290304 Err ( agent
291305 . throw_exception (
292306 ExceptionType :: Error ,
@@ -310,12 +324,14 @@ impl FileExt {
310324 . as_str ( agent)
311325 . expect ( "String is not valid UTF-8" ) ;
312326
313- let storage = Self :: get_blob_storage ( ) ;
314- let storage_lock = storage. lock ( ) . unwrap ( ) ;
327+ let storage = Self :: get_blob_storage_mut ( agent) ;
315328
316- if let Some ( blob) = storage_lock. get ( blob_id) {
317- Ok ( Value :: from_string ( agent, blob. content_type . clone ( ) , gc. nogc ( ) ) . unbind ( ) )
329+ if let Some ( blob) = storage. get ( blob_id) {
330+ let content_type = blob. content_type . clone ( ) ;
331+ drop ( storage) ;
332+ Ok ( Value :: from_string ( agent, content_type, gc. nogc ( ) ) . unbind ( ) )
318333 } else {
334+ drop ( storage) ;
319335 Err ( agent
320336 . throw_exception (
321337 ExceptionType :: Error ,
@@ -339,10 +355,9 @@ impl FileExt {
339355 . as_str ( agent)
340356 . expect ( "String is not valid UTF-8" ) ;
341357
342- let storage = Self :: get_blob_storage ( ) ;
343- let storage_lock = storage. lock ( ) . unwrap ( ) ;
358+ let storage = Self :: get_blob_storage_mut ( agent) ;
344359
345- if let Some ( blob) = storage_lock . get ( blob_id) {
360+ if let Some ( blob) = storage . get ( blob_id) {
346361 // Return the blob data as comma-separated bytes for now
347362 // TODO: return a ReadableStream
348363 let bytes_str = blob
@@ -351,8 +366,10 @@ impl FileExt {
351366 . map ( |b| b. to_string ( ) )
352367 . collect :: < Vec < _ > > ( )
353368 . join ( "," ) ;
369+ drop ( storage) ;
354370 Ok ( Value :: from_string ( agent, bytes_str, gc. nogc ( ) ) . unbind ( ) )
355371 } else {
372+ drop ( storage) ;
356373 Err ( agent
357374 . throw_exception (
358375 ExceptionType :: Error ,
@@ -376,19 +393,20 @@ impl FileExt {
376393 . as_str ( agent)
377394 . expect ( "String is not valid UTF-8" ) ;
378395
379- let storage = Self :: get_blob_storage ( ) ;
380- let storage_lock = storage. lock ( ) . unwrap ( ) ;
396+ let storage = Self :: get_blob_storage_mut ( agent) ;
381397
382- if let Some ( blob) = storage_lock . get ( blob_id) {
398+ if let Some ( blob) = storage . get ( blob_id) {
383399 // Return the blob data as comma-separated bytes
384400 let bytes_str = blob
385401 . data
386402 . iter ( )
387403 . map ( |b| b. to_string ( ) )
388404 . collect :: < Vec < _ > > ( )
389405 . join ( "," ) ;
406+ drop ( storage) ;
390407 Ok ( Value :: from_string ( agent, bytes_str, gc. nogc ( ) ) . unbind ( ) )
391408 } else {
409+ drop ( storage) ;
392410 Err ( agent
393411 . throw_exception (
394412 ExceptionType :: Error ,
@@ -412,13 +430,14 @@ impl FileExt {
412430 . as_str ( agent)
413431 . expect ( "String is not valid UTF-8" ) ;
414432
415- let storage = Self :: get_blob_storage ( ) ;
416- let storage_lock = storage. lock ( ) . unwrap ( ) ;
433+ let storage = Self :: get_blob_storage_mut ( agent) ;
417434
418- if let Some ( blob) = storage_lock . get ( blob_id) {
435+ if let Some ( blob) = storage . get ( blob_id) {
419436 let text = String :: from_utf8_lossy ( & blob. data ) . to_string ( ) ;
437+ drop ( storage) ;
420438 Ok ( Value :: from_string ( agent, text, gc. nogc ( ) ) . unbind ( ) )
421439 } else {
440+ drop ( storage) ;
422441 Err ( agent
423442 . throw_exception (
424443 ExceptionType :: Error ,
@@ -493,8 +512,9 @@ impl FileExt {
493512 size,
494513 } ;
495514
496- let storage = Self :: get_blob_storage ( ) ;
497- storage. lock ( ) . unwrap ( ) . insert ( blob_id. clone ( ) , blob) ;
515+ let mut storage = Self :: get_blob_storage_mut ( agent) ;
516+ storage. insert ( blob_id. clone ( ) , blob) ;
517+ drop ( storage) ;
498518
499519 // Return combined data: blob_id:name:last_modified
500520 let result = format ! ( "{blob_id}:{name}:{last_modified}" ) ;
0 commit comments