@@ -571,6 +571,7 @@ function Framework() {
571571 'allow-performance' : false ,
572572 'allow-custom-titles' : false ,
573573 'allow-cache-snapshot' : false ,
574+ 'allow-defer' : true ,
574575 'disable-strict-server-certificate-validation' : true ,
575576 'disable-clear-temporary-directory' : false ,
576577
@@ -667,7 +668,8 @@ function Framework() {
667668 other : { } ,
668669 internal : { } , // controllers/modules names for the routing
669670 owners : { } ,
670- ready : { }
671+ ready : { } ,
672+ defer : { }
671673 } ;
672674
673675 this . stats = {
@@ -2750,6 +2752,12 @@ F.error = function(err, name, uri) {
27502752 F . errors . length > 50 && F . errors . shift ( ) ;
27512753 }
27522754
2755+ if ( ! name && ! uri && err . stack ) {
2756+ var defer = err . stack . match ( / \/ \w + \/ d e f e r \- .* ?\. j s / ) ;
2757+ if ( defer )
2758+ err . stack = err . stack . replace ( defer , defer . toString ( ) ) . replace ( / \/ \w + \/ d e f e r \- / , '/' ) . split ( '$' ) . join ( '/' ) ;
2759+ }
2760+
27532761 F . onError ( err , name , uri ) ;
27542762 return F ;
27552763} ;
@@ -3243,7 +3251,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
32433251
32443252 if ( type === 'middleware' ) {
32453253
3246- F . routes . middleware [ name ] = typeof ( declaration ) === 'function' ? declaration : eval ( declaration ) ;
3254+ F . routes . middleware [ name ] = typeof ( declaration ) === 'function' ? declaration : eval ( parseDefer ( declaration ) ) ;
32473255 F . _length_middleware = Object . keys ( F . routes . middleware ) . length ;
32483256
32493257 next && next ( ) ;
@@ -3362,7 +3370,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
33623370 try {
33633371 var filecomponent = F . path . temp ( 'component-' + name + '.js' ) ;
33643372 _owner = ( packageName ? packageName + '@' : '' ) + type + '#' + name ;
3365- Fs . writeFileSync ( filecomponent , content . install . trim ( ) ) ;
3373+ Fs . writeFileSync ( filecomponent , parseDefer ( content . install . trim ( ) ) ) ;
33663374 obj = require ( filecomponent ) ;
33673375
33683376 ( function ( name ) {
@@ -3444,6 +3452,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
34443452 if ( type === 'theme' ) {
34453453
34463454 _owner = ( packageName ? packageName + '@' : '' ) + type + '#' + name ;
3455+ declaration = parseDeferFile ( type , declaration ) ;
34473456 obj = require ( declaration ) ;
34483457 obj . $owner = _owner ;
34493458 F . temporary . owners [ _owner ] = true ;
@@ -3525,6 +3534,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
35253534 try {
35263535
35273536 if ( useRequired ) {
3537+ declaration = parseDeferFile ( type , declaration ) ;
35283538 delete require . cache [ require . resolve ( declaration ) ] ;
35293539 obj = require ( declaration ) ;
35303540
@@ -3533,7 +3543,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
35333543 } ) ( require . resolve ( declaration ) ) ;
35343544 }
35353545 else
3536- obj = typeof ( declaration ) === 'function' ? eval ( '(' + declaration . toString ( ) + ')()' ) : eval ( declaration ) ;
3546+ obj = typeof ( declaration ) === 'function' ? eval ( '(' + parseDefer ( declaration . toString ( ) ) + ')()' ) : eval ( parseDefer ( declaration ) ) ;
35373547
35383548 } catch ( ex ) {
35393549 err = ex ;
@@ -3572,6 +3582,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
35723582 }
35733583
35743584 if ( useRequired ) {
3585+ declaration = parseDeferFile ( type , declaration ) ;
35753586 delete require . cache [ require . resolve ( declaration ) ] ;
35763587 obj = require ( declaration ) ;
35773588 content = Fs . readFileSync ( declaration ) . toString ( ENCODING ) ;
@@ -3580,7 +3591,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
35803591 } ) ( require . resolve ( declaration ) ) ;
35813592 }
35823593 else {
3583- obj = typeof ( declaration ) === 'function' ? eval ( '(' + declaration . toString ( ) + ')()' ) : eval ( declaration ) ;
3594+ obj = typeof ( declaration ) === 'function' ? eval ( '(' + parseDefer ( declaration . toString ( ) ) + ')()' ) : eval ( parseDefer ( declaration ) ) ;
35843595 content = declaration . toString ( ) ;
35853596 }
35863597
@@ -3633,6 +3644,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
36333644 try {
36343645
36353646 if ( useRequired ) {
3647+ declaration = parseDeferFile ( type , declaration ) ;
36363648 obj = require ( declaration ) ;
36373649 ( function ( name ) {
36383650 setTimeout ( ( ) => delete require . cache [ name ] , 1000 ) ;
@@ -3650,7 +3662,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
36503662 }
36513663
36523664 var filename = F . path . temporary ( plus + 'installed-' + type + '-' + U . GUID ( 10 ) + '.js' ) ;
3653- Fs . writeFileSync ( filename , declaration ) ;
3665+ Fs . writeFileSync ( filename , parseDefer ( declaration ) ) ;
36543666 obj = require ( filename ) ;
36553667
36563668 ( function ( name , filename ) {
@@ -3733,6 +3745,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
37333745
37343746 try {
37353747 if ( useRequired ) {
3748+ declaration = parseDeferFile ( type , declaration ) ;
37363749 obj = require ( declaration ) ;
37373750 ( function ( name ) {
37383751 setTimeout ( function ( ) {
@@ -3751,7 +3764,7 @@ F.install = function(type, name, declaration, options, callback, internal, useRe
37513764 }
37523765
37533766 filename = F . path . temporary ( plus + 'installed-' + type + '-' + U . GUID ( 10 ) + '.js' ) ;
3754- Fs . writeFileSync ( filename , declaration ) ;
3767+ Fs . writeFileSync ( filename , parseDefer ( declaration ) ) ;
37553768 obj = require ( filename ) ;
37563769 ( function ( name , filename ) {
37573770 setTimeout ( function ( ) {
@@ -3965,7 +3978,8 @@ F.$restart = function() {
39653978 other : { } ,
39663979 internal : { } ,
39673980 owners : { } ,
3968- ready : { }
3981+ ready : { } ,
3982+ defer : { }
39693983 } ;
39703984
39713985 F . modificators = null ;
@@ -4854,6 +4868,7 @@ F.usage = function(detailed) {
48544868 var staticNotfound = Object . keys ( F . temporary . notfound ) ;
48554869 var staticRange = Object . keys ( F . temporary . range ) ;
48564870 var redirects = Object . keys ( F . routes . redirects ) ;
4871+ var defer = Object . keys ( F . temporary . defer ) ;
48574872 var output = { } ;
48584873
48594874 output . framework = {
@@ -4895,7 +4910,8 @@ F.usage = function(detailed) {
48954910 streaming : staticRange . length ,
48964911 modificator : F . modificators ? F . modificators . length : 0 ,
48974912 viewphrases : $VIEWCACHE . length ,
4898- uptodates : F . uptodates ? F . uptodates . length : 0
4913+ uptodates : F . uptodates ? F . uptodates . length : 0 ,
4914+ defer : defer . length
48994915 } ;
49004916
49014917 output . routing = {
@@ -15260,6 +15276,63 @@ function parseSchema(name) {
1526015276 return schema ;
1526115277}
1526215278
15279+ function parseDefer ( code ) {
15280+
15281+ if ( ! F . config [ 'allow-defer' ] )
15282+ return code ;
15283+
15284+ var beg = code . indexOf ( 'function DEFER(' ) ;
15285+ if ( beg === - 1 )
15286+ return code ;
15287+
15288+ var b = code . indexOf ( '{' , beg ) ;
15289+ var end = - 1 ;
15290+ var count = 0 ;
15291+ var indexer = b + 1 ;
15292+
15293+ while ( true ) {
15294+ var c = code [ indexer ++ ] ;
15295+
15296+ if ( ! c )
15297+ break ;
15298+
15299+ if ( c === '{' ) {
15300+ count ++ ;
15301+ continue ;
15302+ }
15303+
15304+ if ( c === '}' ) {
15305+ if ( count ) {
15306+ count -- ;
15307+ continue ;
15308+ }
15309+ end = indexer ;
15310+ break ;
15311+ }
15312+ }
15313+
15314+ if ( end === - 1 )
15315+ return code ;
15316+
15317+ var scope = code . substring ( beg , end ) ;
15318+ var id = 'D' + scope . hash ( ) . toString ( ) . replace ( '-' , '_' ) ;
15319+ code = code . replace ( scope , 'F.temporary.defer.' + id ) ;
15320+ scope = U . minifyScript ( scope . trim ( ) . replace ( ' DEFER(' , '(' ) ) ;
15321+ F . temporary . defer [ id ] = new Function ( 'return ' + parseDefer ( scope ) ) ( ) ;
15322+ return parseDefer ( code ) ;
15323+ }
15324+
15325+ function parseDeferFile ( type , filename ) {
15326+ if ( ! F . config [ 'allow-defer' ] )
15327+ return filename ;
15328+ var data = Fs . readFileSync ( filename ) . toString ( ENCODING ) ;
15329+ if ( data . indexOf ( ' DEFER(' ) === - 1 )
15330+ return filename ;
15331+ var tmp = F . path . temp ( 'defer-' + type + '$' + U . getName ( filename ) ) ;
15332+ Fs . writeFileSync ( tmp , parseDefer ( data ) ) ;
15333+ return tmp ;
15334+ }
15335+
1526315336// Because of controller prototypes
1526415337// It's used in F.view() and F.viewCompile()
1526515338const EMPTYCONTROLLER = new Controller ( '' , null , null , null , '' ) ;
0 commit comments