@@ -743,17 +743,14 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
743743 }
744744
745745 // compile and eval a JS module
746- // It doesn't wait for callbacks execution
747- pub fn module (self : * JsContext , src : []const u8 , url : []const u8 , cacheable : bool ) ! void {
748- if (! cacheable ) {
749- return self .moduleNoCache (src , url );
750- }
751-
746+ // It returns null if the module is already compiled and in the cache.
747+ // It returns a v8.Promise if the module must be evaluated.
748+ pub fn module (self : * JsContext , src : []const u8 , url : []const u8 , cacheable : bool ) ! ? v8.Promise {
752749 const arena = self .context_arena ;
753750
754- const gop = try self . module_cache . getOrPut ( arena , url );
755- if ( gop . found_existing ) {
756- return ;
751+ if ( cacheable ) {
752+ const value = self . module_cache . get ( url );
753+ if ( value != null ) return null ;
757754 }
758755 errdefer _ = self .module_cache .remove (url );
759756
@@ -763,30 +760,22 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
763760 try self .module_identifier .putNoClobber (arena , m .getIdentityHash (), owned_url );
764761 errdefer _ = self .module_identifier .remove (m .getIdentityHash ());
765762
766- gop .key_ptr .* = owned_url ;
767- gop .value_ptr .* = PersistentModule .init (self .isolate , m );
763+ if (cacheable ) {
764+ try self .module_cache .put (arena , owned_url , PersistentModule .init (self .isolate , m ));
765+ }
768766
769767 // resolveModuleCallback loads module's dependencies.
770768 const v8_context = self .v8_context ;
771769 if (try m .instantiate (v8_context , resolveModuleCallback ) == false ) {
772770 return error .ModuleInstantiationError ;
773771 }
774772
775- _ = try m .evaluate (v8_context );
776- }
777-
778- fn moduleNoCache (self : * JsContext , src : []const u8 , url : []const u8 ) ! void {
779- const m = try compileModule (self .isolate , src , url );
780-
781- const arena = self .context_arena ;
782- const owned_url = try arena .dupe (u8 , url );
783- try self .module_identifier .putNoClobber (arena , m .getIdentityHash (), owned_url );
784-
785- const v8_context = self .v8_context ;
786- if (try m .instantiate (v8_context , resolveModuleCallback ) == false ) {
787- return error .ModuleInstantiationError ;
788- }
789- _ = try m .evaluate (v8_context );
773+ const evaluated = try m .evaluate (v8_context );
774+ // https://v8.github.io/api/head/classv8_1_1Module.html#a1f1758265a4082595757c3251bb40e0f
775+ // Must be a promise that gets returned here.
776+ std .debug .assert (evaluated .isPromise ());
777+ const promise = v8.Promise { .handle = evaluated .handle };
778+ return promise ;
790779 }
791780
792781 // Wrap a v8.Exception
@@ -1545,32 +1534,32 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
15451534 .{ .alloc = .if_needed },
15461535 ) catch unreachable ;
15471536
1548- _dynamicModuleCallback (context , resource_str , normalized_specifier , & resolver );
1537+ log .debug (.js , "dynamic import" , .{
1538+ .specifier = specifier_str ,
1539+ .resource = resource_str ,
1540+ .referrer_full = referrer_full_url ,
1541+ .normalized_specifier = normalized_specifier ,
1542+ });
1543+
1544+ _dynamicModuleCallback (context , normalized_specifier , & resolver ) catch | err | {
1545+ log .err (.js , "dynamic module callback" , .{
1546+ .err = err ,
1547+ });
1548+ // Must be rejected at this point
1549+ // otherwise, we will just wait on a pending promise.
1550+ std .debug .assert (resolver .getPromise ().getState () == .kRejected );
1551+ };
15491552 return @constCast (resolver .getPromise ().handle );
15501553 }
15511554
15521555 fn _dynamicModuleCallback (
15531556 context : * JsContext ,
1554- resource : []const u8 ,
15551557 specifier : []const u8 ,
15561558 resolver : * const v8.PromiseResolver ,
1557- ) void {
1559+ ) ! void {
15581560 const iso = context .isolate ;
15591561 const ctx = context .v8_context ;
15601562
1561- // Check module cache first.
1562- if (context .module_cache .get (specifier )) | cached_module | {
1563- const namespace = cached_module .castToModule ().getModuleNamespace ();
1564- _ = resolver .resolve (ctx , namespace );
1565- return ;
1566- }
1567-
1568- log .info (.js , "dynamic import" , .{
1569- .specifier = specifier ,
1570- .resource = resource ,
1571- .normalized = specifier ,
1572- });
1573-
15741563 const module_loader = context .module_loader ;
15751564 const source = module_loader .func (module_loader .ptr , specifier ) catch {
15761565 const error_msg = v8 .String .initUtf8 (iso , "Failed to load module" );
@@ -1586,71 +1575,30 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
15861575 try_catch .init (context );
15871576 defer try_catch .deinit ();
15881577
1589- const new_module = compileModule ( iso , source , specifier ) catch {
1578+ const maybe_promise = context . module ( source , specifier , true ) catch {
15901579 log .err (.js , "module compilation failed" , .{
15911580 .specifier = specifier ,
15921581 .exception = try_catch .exception (context .call_arena ) catch "unknown error" ,
15931582 .stack = try_catch .stack (context .call_arena ) catch null ,
1594- });
1595- const error_msg = if (try_catch .hasCaught ()) blk : {
1596- const exception_str = try_catch .exception (context .call_arena ) catch "Compilation error" ;
1597- break :blk v8 .String .initUtf8 (iso , exception_str orelse "Compilation error" );
1598- } else v8 .String .initUtf8 (iso , "Module compilation failed" );
1599-
1600- _ = resolver .reject (ctx , error_msg .toValue ());
1601- return ;
1602- };
1603-
1604- // Insert into Module Cache.
1605- context .module_identifier .putNoClobber (context .context_arena , new_module .getIdentityHash (), specifier ) catch unreachable ;
1606- context .module_cache .putNoClobber (context .context_arena , specifier , v8 .Persistent (v8 .Module ).init (iso , new_module )) catch unreachable ;
1607-
1608- const instantiated = new_module .instantiate (ctx , JsContext .resolveModuleCallback ) catch {
1609- log .err (.js , "module instantiation failed" , .{
1610- .specifier = specifier ,
1611- .exception = try_catch .exception (context .call_arena ) catch "unknown error" ,
1612- .stack = try_catch .stack (context .call_arena ) catch null ,
1613- });
1614- const error_msg = if (try_catch .hasCaught ()) blk : {
1615- const exception_str = try_catch .exception (context .call_arena ) catch "Instantiation error" ;
1616- break :blk v8 .String .initUtf8 (iso , exception_str orelse "Instantiation error" );
1617- } else v8 .String .initUtf8 (iso , "Module instantiation failed" );
1618-
1619- _ = resolver .reject (ctx , error_msg .toValue ());
1620- return ;
1621- };
1622-
1623- if (! instantiated ) {
1624- const error_msg = v8 .String .initUtf8 (iso , "Module did not instantiate" );
1625- _ = resolver .reject (ctx , error_msg .toValue ());
1626- return ;
1627- }
1628-
1629- const evaluated = new_module .evaluate (ctx ) catch {
1630- log .err (.js , "module evaluation failed" , .{
1631- .specifier = specifier ,
1632- .exception = try_catch .exception (context .call_arena ) catch "unknown error" ,
1633- .stack = try_catch .stack (context .call_arena ) catch null ,
16341583 .line = try_catch .sourceLineNumber () orelse 0 ,
16351584 });
16361585 const error_msg = if (try_catch .hasCaught ()) blk : {
16371586 const exception_str = try_catch .exception (context .call_arena ) catch "Evaluation error" ;
16381587 break :blk v8 .String .initUtf8 (iso , exception_str orelse "Evaluation error" );
16391588 } else v8 .String .initUtf8 (iso , "Module evaluation failed" );
1640-
16411589 _ = resolver .reject (ctx , error_msg .toValue ());
16421590 return ;
16431591 };
1592+ const new_module = context .module_cache .get (specifier ).? .castToModule ();
16441593
1645- if (evaluated .isPromise ()) {
1646- const promise = v8.Promise { .handle = evaluated .handle };
1647-
1594+ if (maybe_promise ) | promise | {
1595+ // This means we must wait for the evaluation.
16481596 const EvaluationData = struct {
16491597 module : v8 .Persistent (v8 .Module ),
16501598 resolver : v8 .Persistent (v8 .PromiseResolver ),
16511599 };
16521600
1653- const ev_data = context .context_arena .create (EvaluationData ) catch unreachable ;
1601+ const ev_data = try context .context_arena .create (EvaluationData );
16541602 ev_data .* = .{
16551603 .module = v8 .Persistent (v8 .Module ).init (iso , new_module ),
16561604 .resolver = v8 .Persistent (v8 .PromiseResolver ).init (iso , resolver .* ),
@@ -1667,7 +1615,8 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
16671615 const cb_resolver = data .resolver .castToPromiseResolver ();
16681616
16691617 const namespace = cb_module .getModuleNamespace ();
1670- log .warn (.js , "module then promise" , .{
1618+ log .info (.js , "dynamic import complete" , .{
1619+ .module = cb_module ,
16711620 .namespace = namespace ,
16721621 });
16731622 _ = cb_resolver .resolve (cb_context , namespace );
@@ -1676,11 +1625,15 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
16761625
16771626 const catch_callback = v8 .Function .initWithData (ctx , struct {
16781627 pub fn callback (info : ? * const v8.c.FunctionCallbackInfo ) callconv (.c ) void {
1679- log .warn (.js , "module catch promise" , .{});
16801628 const cb_info = v8.FunctionCallbackInfo { .handle = info .? };
16811629 const cb_context = cb_info .getIsolate ().getCurrentContext ();
16821630 const data : * EvaluationData = @ptrCast (@alignCast (cb_info .getExternalValue ()));
1631+ const cb_module = data .module .castToModule ();
16831632 const cb_resolver = data .resolver .castToPromiseResolver ();
1633+
1634+ log .err (.js , "dynamic import failed" , .{
1635+ .module = cb_module ,
1636+ });
16841637 _ = cb_resolver .reject (cb_context , cb_info .getData ());
16851638 }
16861639 }.callback , external );
@@ -1695,8 +1648,14 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
16951648 return ;
16961649 };
16971650 } else {
1651+ // This means it is already present in the cache.
16981652 const namespace = new_module .getModuleNamespace ();
1653+ log .info (.js , "dynamic import complete" , .{
1654+ .module = new_module ,
1655+ .namespace = namespace ,
1656+ });
16991657 _ = resolver .resolve (ctx , namespace );
1658+ return ;
17001659 }
17011660 }
17021661 };
0 commit comments