@@ -101,6 +101,29 @@ ClazzLoader.clazzTreeRoot = new ClazzNode ();
101101/*-# loadedScripts -> ls #-*/
102102ClazzLoader . loadedScripts = new Object ( ) ;
103103
104+ /**
105+ * Multiple threads are used to speed up *.js loading.
106+ */
107+ /* private */
108+ /*-# inLoadingThreads -> ilt #-*/
109+ ClazzLoader . inLoadingThreads = 0 ;
110+
111+ /**
112+ * Maximum of loading threads
113+ */
114+ /* protected */
115+ ClazzLoader . maxLoadingThreads = 6 ;
116+
117+ /*
118+ * Opera has different loading order which will result in performance degrade!
119+ * So just return to single thread loading in Opera!
120+ *
121+ * FIXME: This different loading order also causes bugs in single thread!
122+ */
123+ if ( navigator . userAgent . toLowerCase ( ) . indexOf ( "opera" ) != - 1 ) {
124+ ClazzLoader . maxLoadingThreads = 1 ;
125+ }
126+
104127/**
105128 * Try to be compatiable with Clazz system.
106129 */
@@ -584,9 +607,6 @@ ClazzLoader.xhrOnload = function (transport, file) {
584607ClazzLoader . emptyOnRSC = function ( ) {
585608} ;
586609
587- /* private */
588- ClazzLoader . lastScriptPath = null ;
589-
590610/* protected */
591611/*-# failedScripts -> fss #-*/
592612ClazzLoader . failedScripts = new Object ( ) ;
@@ -614,7 +634,6 @@ ClazzLoader.loadScript = function (file) {
614634 ClazzLoader . tryToLoadNext ( file ) ;
615635 return ;
616636 }
617- ClazzLoader . lastScriptPath = file ;
618637 ClazzLoader . loadedScripts [ file ] = true ;
619638
620639 if ( ClazzLoader . isUsingXMLHttpRequest ) {
@@ -641,6 +660,9 @@ ClazzLoader.loadScript = function (file) {
641660 if ( ClazzLoader . isAsynchronousLoading ) {
642661 transport . onreadystatechange = function ( ) {
643662 if ( transport . readyState == 4 ) {
663+ if ( ClazzLoader . inLoadingThreads > 0 ) {
664+ ClazzLoader . inLoadingThreads -- ;
665+ }
644666 if ( isActiveX ) {
645667 transport . onreadystatechange = ClazzLoader . emptyOnRSC ;
646668 // For IE, try to avoid stack overflow errors
@@ -660,6 +682,7 @@ ClazzLoader.loadScript = function (file) {
660682 }
661683 }
662684 } ;
685+ ClazzLoader . inLoadingThreads ++ ;
663686 try {
664687 transport . send ( null ) ;
665688 } catch ( e ) {
@@ -698,6 +721,9 @@ ClazzLoader.loadScript = function (file) {
698721 * Opera will trigger onload event even there are no *.js existed
699722 */
700723 script . onload = function ( ) {
724+ if ( ClazzLoader . inLoadingThreads > 0 ) {
725+ ClazzLoader . inLoadingThreads -- ;
726+ }
701727 this . onload = null ;
702728 var path = arguments . callee . path ;
703729 if ( ! ClazzLoader . isInnerLoaded
@@ -729,6 +755,9 @@ ClazzLoader.loadScript = function (file) {
729755 * For Firefox/Mozilla, unexisted *.js will result in errors.
730756 */
731757 script . onerror = function ( ) { // Firefox/Mozilla
758+ if ( ClazzLoader . inLoadingThreads > 0 ) {
759+ ClazzLoader . inLoadingThreads -- ;
760+ }
732761 this . onerror = null ;
733762 var path = arguments . callee . path ;
734763 var fss = ClazzLoader . failedScripts ;
@@ -784,6 +813,10 @@ ClazzLoader.loadScript = function (file) {
784813 // next time in "loading" state won't get waiting!
785814 ClazzLoader . failedScripts [ path ] = 0 ;
786815 ClazzLoader . loadedScripts [ path ] = false ;
816+ // failed count down!
817+ if ( ClazzLoader . inLoadingThreads > 0 ) {
818+ ClazzLoader . inLoadingThreads -- ;
819+ }
787820 // Take another try!
788821 ClazzLoader . loadScript ( path ) ;
789822 } ;
@@ -797,7 +830,7 @@ ClazzLoader.loadScript = function (file) {
797830 fhs [ path ] = window . setTimeout ( fun , waitingTime ) ;
798831 return ;
799832 }
800- if ( fss [ path ] == 1 ) {
833+ if ( fss [ path ] == 1 ) { // above function will be executed?!
801834 return ;
802835 }
803836 }
@@ -807,6 +840,10 @@ ClazzLoader.loadScript = function (file) {
807840 }
808841 if ( ( local || state == "loaded" ) && ! ClazzLoader . isInnerLoaded ) {
809842 if ( ! local && ( fss [ path ] == null || fss [ path ] == 0 ) ) {
843+ // failed! count down
844+ if ( ClazzLoader . inLoadingThreads > 0 ) {
845+ ClazzLoader . inLoadingThreads -- ;
846+ }
810847 // silently take another try for bad network
811848 fss [ path ] = 1 ;
812849 // log ("reloading ... " + path);
@@ -817,6 +854,9 @@ ClazzLoader.loadScript = function (file) {
817854 alert ( "[Java2Script] Error in loading " + path + "!" ) ;
818855 }
819856 }
857+ if ( ClazzLoader . inLoadingThreads > 0 ) {
858+ ClazzLoader . inLoadingThreads -- ;
859+ }
820860 ClazzLoader . scriptLoaded ( path ) ;
821861 // Unset onreadystatechange, leaks mem in IE
822862 this . onreadystatechange = null ;
@@ -831,6 +871,8 @@ ClazzLoader.loadScript = function (file) {
831871 script . onreadystatechange . path = file ;
832872 }
833873 ClazzLoader . isInnerLoaded = false ;
874+ ClazzLoader . inLoadingThreads ++ ;
875+ //alert("threads:"+ClazzLoader.inLoadingThreads);
834876 // Add script DOM element to document tree
835877 head . appendChild ( script ) ;
836878 ClazzLoader . scriptLoading ( file ) ;
@@ -873,6 +915,7 @@ ClazzLoader.isResourceExisted = function (id, path, base) {
873915 }
874916 return false ;
875917} ;
918+
876919/**
877920 * After class is loaded, this method will be executed to check whether there
878921 * are classes in the dependency tree that need to be loaded.
@@ -904,7 +947,13 @@ ClazzLoader.tryToLoadNext = function (file) {
904947 } else {
905948 n = new ClazzNode ( ) ;
906949 n . name = nm ;
907- n . path = ClazzLoader . lastScriptPath ;
950+ var pp = ClazzLoader . classpathMap [ "#" + nm ] ;
951+ if ( pp == null ) {
952+ log ( nm ) ;
953+ error ( "Java2Script implementation error! Please report this bug!" ) ;
954+ }
955+ //n.path = ClazzLoader.lastScriptPath;
956+ n . path = pp ;
908957 //error ("..." + node.path + "//" + node.name);
909958 ClazzLoader . mappingPathNameNode ( n . path , nm , n ) ;
910959 n . status = ClazzNode . STATUS_CONTENT_LOADED ;
@@ -941,14 +990,21 @@ ClazzLoader.tryToLoadNext = function (file) {
941990 var loadFurther = false ;
942991 var n = ClazzLoader . findNextMustClass ( ClazzLoader . clazzTreeRoot ,
943992 ClazzNode . STATUS_KNOWN ) ;
944- //alert (" next..." + n) ;
993+ //alert (file + " next ..." + n) ;
945994 if ( n != null ) {
946995 //log ("next ..." + n.name);
947996 ClazzLoader . loadClassNode ( n ) ;
997+ while ( ClazzLoader . inLoadingThreads < ClazzLoader . maxLoadingThreads ) {
998+ var nn = ClazzLoader . findNextMustClass ( ClazzLoader . clazzTreeRoot ,
999+ ClazzNode . STATUS_KNOWN ) ;
1000+ if ( nn == null ) break ;
1001+ ClazzLoader . loadClassNode ( nn ) ; // will increase inLoadingThreads!
1002+ }
9481003 } else {
9491004 var cq = ClazzLoader . classQueue ;
950- if ( cq . length != 0 ) {
951- n = cq [ 0 ] ; // popup class from the quue
1005+ if ( cq . length != 0 ) {
1006+ /* queue must be loaded in order! */
1007+ n = cq [ 0 ] ; // popup class from the queue
9521008 for ( var i = 0 ; i < cq . length - 1 ; i ++ ) {
9531009 cq [ i ] = cq [ i + 1 ] ;
9541010 }
@@ -958,16 +1014,23 @@ ClazzLoader.tryToLoadNext = function (file) {
9581014 //alert ("load from queue");
9591015 ClazzLoader . loadScript ( n . path ) ;
9601016 } else { // Optionals
1017+ //log ("options");
9611018 n = ClazzLoader . findNextOptionalClass ( ClazzNode . STATUS_KNOWN ) ;
9621019 if ( n != null ) {
9631020 //log ("in optionals unknown..." + n.name);
9641021 ClazzLoader . loadClassNode ( n ) ;
1022+ while ( ClazzLoader . inLoadingThreads < ClazzLoader . maxLoadingThreads ) {
1023+ var nn = ClazzLoader . findNextOptionalClass ( ClazzNode . STATUS_KNOWN ) ;
1024+ //log ("in second loading " + nn);
1025+ if ( nn == null ) break ;
1026+ ClazzLoader . loadClassNode ( nn ) ; // will increase inLoadingThreads!
1027+ }
9651028 } else {
9661029 loadFurther = true ;
9671030 }
9681031 }
9691032 }
970- if ( loadFurther ) {
1033+ if ( loadFurther && ClazzLoader . inLoadingThreads == 0 ) {
9711034 //error ("no optionals?");
9721035 while ( ( n = ClazzLoader . findNextMustClass ( ClazzLoader . clazzTreeRoot , ClazzNode . STATUS_CONTENT_LOADED ) ) != null ) {
9731036 ClazzLoader . updateNode ( n ) ;
@@ -1235,7 +1298,9 @@ ClazzLoader.findNextMustClass = function (node, status) {
12351298 if ( node . musts != null && node . musts . length != 0 ) {
12361299 for ( var i = 0 ; i < node . musts . length ; i ++ ) {
12371300 var n = node . musts [ i ] ;
1238- if ( n . status == status ) {
1301+ if ( n . status == status && ( status != ClazzNode . STATUS_KNOWN
1302+ || ClazzLoader . loadedScripts [ n . path ] != true )
1303+ && ! ClazzLoader . isClassDefined ( n . name ) ) {
12391304 return n ;
12401305 } else {
12411306 var nn = ClazzLoader . findNextMustClass ( n , status ) ;
@@ -1245,7 +1310,9 @@ ClazzLoader.findNextMustClass = function (node, status) {
12451310 }
12461311 }
12471312 }
1248- if ( node . status == status ) {
1313+ if ( node . status == status && ( status != ClazzNode . STATUS_KNOWN
1314+ || ClazzLoader . loadedScripts [ node . path ] != true )
1315+ && ! ClazzLoader . isClassDefined ( node . name ) ) {
12491316 return node ;
12501317 }
12511318 }
@@ -1271,19 +1338,25 @@ ClazzLoader.findNodeNextOptionalClass = function (node, status) {
12711338 // search musts first
12721339 if ( node . musts != null && node . musts . length != 0 ) {
12731340 var n = ClazzLoader . searchClassArray ( node . musts , rnd , status ) ;
1274- if ( n != null ) {
1341+ if ( n != null && ( status != ClazzNode . STATUS_KNOWN
1342+ || ClazzLoader . loadedScripts [ n . path ] != true )
1343+ && ! ClazzLoader . isClassDefined ( n . name ) ) {
12751344 return n ;
12761345 }
12771346 }
12781347 // search optionals second
12791348 if ( node . optionals != null && node . optionals . length != 0 ) {
12801349 var n = ClazzLoader . searchClassArray ( node . optionals , rnd , status ) ;
1281- if ( n != null ) {
1350+ if ( n != null && ( status != ClazzNode . STATUS_KNOWN
1351+ || ClazzLoader . loadedScripts [ n . path ] != true )
1352+ && ! ClazzLoader . isClassDefined ( n . name ) ) {
12821353 return n ;
12831354 }
12841355 }
12851356 // search itself
1286- if ( node . status == status ) {
1357+ if ( node . status == status && ( status != ClazzNode . STATUS_KNOWN
1358+ || ClazzLoader . loadedScripts [ node . path ] != true )
1359+ && ! ClazzLoader . isClassDefined ( node . name ) ) {
12871360 return node ;
12881361 }
12891362 return null ;
@@ -1293,7 +1366,9 @@ ClazzLoader.findNodeNextOptionalClass = function (node, status) {
12931366ClazzLoader . searchClassArray = function ( arr , rnd , status ) {
12941367 for ( var i = 0 ; i < arr . length ; i ++ ) {
12951368 var n = arr [ i ] ;
1296- if ( n . status == status ) {
1369+ if ( n . status == status && ( status != ClazzNode . STATUS_KNOWN
1370+ || ClazzLoader . loadedScripts [ n . path ] != true )
1371+ && ! ClazzLoader . isClassDefined ( n . name ) ) {
12971372 return n ;
12981373 } else {
12991374 if ( n . random == rnd ) {
@@ -1345,7 +1420,13 @@ ClazzLoader.load = function (musts, clazz, optionals, declaration) {
13451420 //*
13461421 //node = new ClazzNode ();
13471422 node . name = clazz ;
1348- node . path = ClazzLoader . lastScriptPath ;
1423+ var pp = ClazzLoader . classpathMap [ "#" + clazz ] ;
1424+ if ( pp == null ) {
1425+ log ( clazz ) ;
1426+ error ( "Java2Script implementation error! Please report this bug!" ) ;
1427+ }
1428+ //node.path = ClazzLoader.lastScriptPath;
1429+ node . path = pp ;
13491430 //error ("..." + node.path + "//" + node.name);
13501431 ClazzLoader . mappingPathNameNode ( node . path , clazz , node ) ;
13511432 node . status = ClazzNode . STATUS_KNOWN ;
@@ -1498,6 +1579,12 @@ ClazzLoader.findClassUnderNode = function (clazzName, node) {
14981579 return null ;
14991580} ;
15001581
1582+ /**
1583+ * Map different class to the same path!
1584+ * @path *.js path
1585+ * @name class name
1586+ * @node ClazzNode object
1587+ */
15011588/* private */
15021589/*-# mappingPathNameNode -> mpp #-*/
15031590ClazzLoader . mappingPathNameNode = function ( path , name , node ) {
@@ -1539,8 +1626,10 @@ ClazzLoader.loadClassNode = function (node) {
15391626 ClazzLoader . mappingPathNameNode ( path , name , node ) ;
15401627 if ( ! ClazzLoader . loadedScripts [ path ] ) {
15411628 ClazzLoader . loadScript ( path ) ;
1629+ return true ;
15421630 }
15431631 }
1632+ return false ;
15441633} ;
15451634
15461635
0 commit comments