@@ -471,7 +471,7 @@ function logloads(loads) {
471471 /***/
472472 if ( linkSet . loader . loaderObj . execute === false ) {
473473 var loads = [ ] . concat ( linkSet . loads ) ;
474- for ( var i = 0 ; i < loads . length ; i ++ ) {
474+ for ( var i = 0 , l = loads . length ; i < l ; i ++ ) {
475475 var load = loads [ i ] ;
476476 load . module = load . kind == 'dynamic' ? {
477477 module : _newModule ( { } )
@@ -575,7 +575,7 @@ function logloads(loads) {
575575 // now add it to the group to indicate its been seen
576576 groups [ load . groupIndex ] . push ( load ) ;
577577
578- for ( var i = 0 ; i < loads . length ; i ++ ) {
578+ for ( var i = 0 , l = loads . length ; i < l ; i ++ ) {
579579 var loadDep = loads [ i ] ;
580580
581581 // dependencies not found are already linked
@@ -661,77 +661,79 @@ function logloads(loads) {
661661 }
662662 }
663663
664+
665+ // custom module records for binding graph
666+ // store linking module records in a separate table
667+ var moduleRecords = { } ;
668+ function getOrCreateModuleRecord ( name ) {
669+ return moduleRecords [ name ] || ( moduleRecords [ name ] = {
670+ name : name ,
671+ dependencies : [ ] ,
672+ module : new Module ( ) , // start from an empty module and extend
673+ importers : [ ] ,
674+ evaluated : false
675+ } ) ;
676+ }
677+
664678 // custom declarative linking function
665679 function linkDeclarativeModule ( load , loads , loader ) {
666680 if ( load . module )
667681 return ;
668682
669- // declare the module with an empty depMap
670- var depMap = [ ] ;
671-
672- var registryEntry = load . declare . call ( __global , depMap ) ;
673-
674- var moduleDependencies = [ ] ;
683+ var module = load . module = getOrCreateModuleRecord ( load . name ) ;
684+ var moduleObj = load . module . module ;
685+
686+ var registryEntry = load . declare . call ( __global , function ( name , value ) {
687+ // NB This should be an Object.defineProperty, but that is very slow.
688+ // By disaling this module write-protection we gain performance.
689+ // It could be useful to allow an option to enable or disable this.
690+ module . locked = true ;
691+ moduleObj [ name ] = value ;
692+
693+ for ( var i = 0 , l = module . importers . length ; i < l ; i ++ ) {
694+ var importerModule = module . importers [ i ] ;
695+ if ( ! importerModule . locked ) {
696+ var importerIndex = importerModule . dependencies . indexOf ( module ) ;
697+ importerModule . setters [ importerIndex ] ( moduleObj ) ;
698+ }
699+ }
675700
676- // module is just a plain object, until we evaluate it
677- var module = registryEntry . exports ;
701+ module . locked = false ;
702+ return value ;
703+ } ) ;
678704
679- console . assert ( ! load . module , 'Load module already declared!' ) ;
680-
681- load . module = {
682- name : load . name ,
683- dependencies : moduleDependencies ,
684- execute : registryEntry . execute ,
685- exports : module ,
686- evaluated : false
687- } ;
705+ // setup our setters and execution function
706+ load . module . setters = registryEntry . setters ;
707+ load . module . execute = registryEntry . execute ;
688708
689709 // now link all the module dependencies
690710 // amending the depMap as we go
691- for ( var i = 0 ; i < load . dependencies . length ; i ++ ) {
711+ for ( var i = 0 , l = load . dependencies . length ; i < l ; i ++ ) {
692712 var depName = load . dependencies [ i ] . value ;
693- var depModule ;
694- // if dependency already a module, use that
695- if ( loader . modules [ depName ] ) {
696- depModule = loader . modules [ depName ] ;
697- }
698- else {
713+ var depModule = getOrCreateModuleRecord ( depName ) ;
714+
715+ depModule . importers . push ( module ) ;
716+ module . dependencies . push ( depModule ) ;
717+
718+ // if not already a module in the registry, try and link it now
719+ if ( ! loader . modules [ depName ] ) {
720+
721+ // get the dependency load record
699722 for ( var j = 0 ; j < loads . length ; j ++ ) {
700723 if ( loads [ j ] . name != depName )
701724 continue ;
702725
703726 // only link if already not already started linking (stops at circular / dynamic)
704727 if ( ! loads [ j ] . module )
705728 linkDeclarativeModule ( loads [ j ] , loads , loader ) ;
706-
707- depModule = loads [ j ] . module ;
708729 }
709730 }
710731
711- var depModuleModule = depModule . exports || depModule . module ;
712-
713732 console . assert ( depModule , 'Dependency module not found!' ) ;
714733
715- if ( registryEntry . exportStar && indexOf . call ( registryEntry . exportStar , load . dependencies [ i ] . key ) != - 1 ) {
716- // we are exporting * from this dependency
717- ( function ( depModuleModule ) {
718- for ( var p in depModuleModule ) ( function ( p ) {
719- // if the property is already defined throw?
720- defineProperty ( module , p , {
721- enumerable : true ,
722- get : function ( ) {
723- return depModuleModule [ p ] ;
724- } ,
725- set : function ( value ) {
726- depModuleModule [ p ] = value ;
727- }
728- } ) ;
729- } ) ( p ) ;
730- } ) ( depModuleModule ) ;
731- }
732-
733- moduleDependencies . push ( depModule ) ;
734- depMap [ i ] = depModuleModule ;
734+ // run the setter for this dependency
735+ if ( module . setters [ i ] )
736+ module . setters [ i ] ( depModule . module ) ;
735737 }
736738
737739 load . status = 'linked' ;
@@ -759,6 +761,7 @@ function logloads(loads) {
759761 * module.module bound module object
760762 * module.execute execution function for module
761763 * module.dependencies list of module objects for dependencies
764+ * See getOrCreateModuleRecord for all properties
762765 *
763766 */
764767 function doExecute ( module ) {
@@ -787,7 +790,7 @@ function logloads(loads) {
787790 var deps = module . dependencies ;
788791 var err ;
789792
790- for ( var i = 0 ; i < deps . length ; i ++ ) {
793+ for ( var i = 0 , l = deps . length ; i < l ; i ++ ) {
791794 var dep = deps [ i ] ;
792795 if ( indexOf . call ( seen , dep ) == - 1 ) {
793796 err = ensureEvaluated ( dep , seen , loader ) ;
@@ -807,8 +810,13 @@ function logloads(loads) {
807810 err = doExecute ( module ) ;
808811 if ( err )
809812 module . failed = true ;
810- else
811- module . module = _newModule ( module . exports ) ;
813+
814+ // spec variation
815+ // we don't create a new module here because it was created and ammended
816+ // we just disable further extensions instead
817+ if ( Object . preventExtensions )
818+ Object . preventExtensions ( module . module ) ;
819+
812820 module . execute = undefined ;
813821 return err ;
814822 }
0 commit comments