@@ -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,80 @@ 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 = [ ] ;
675-
676- // module is just a plain object, until we evaluate it
677- var module = registryEntry . exports ;
678-
679- console . assert ( ! load . module , 'Load module already declared!' ) ;
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+ moduleObj [ name ] = value ;
691+
692+ for ( var i = 0 , l = module . importers . length ; i < l ; i ++ ) {
693+ var importerModule = module . importers [ i ] ;
694+ if ( importerModule . setters ) {
695+ var importerIndex = importerModule . dependencies . indexOf ( module ) ;
696+ if ( importerIndex != - 1 ) {
697+ var setter = importerModule . setters [ importerIndex ] ;
698+ setter ( moduleObj ) ;
699+ }
700+ }
701+ }
702+ return value ;
703+ } ) ;
680704
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+
717+ // if not already a module in the registry, try and link it now
718+ if ( ! loader . modules [ depName ] ) {
719+
720+ // get the dependency load record
699721 for ( var j = 0 ; j < loads . length ; j ++ ) {
700722 if ( loads [ j ] . name != depName )
701723 continue ;
702724
703725 // only link if already not already started linking (stops at circular / dynamic)
704726 if ( ! loads [ j ] . module )
705727 linkDeclarativeModule ( loads [ j ] , loads , loader ) ;
706-
707- depModule = loads [ j ] . module ;
708728 }
709729 }
710730
711- var depModuleModule = depModule . exports || depModule . module ;
712-
713731 console . assert ( depModule , 'Dependency module not found!' ) ;
714732
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- }
733+ module . dependencies . push ( depModule ) ;
732734
733- moduleDependencies . push ( depModule ) ;
734- depMap [ i ] = depModuleModule ;
735+ // run the setter for this dependency
736+ if ( module . setters [ i ] )
737+ module . setters [ i ] ( depModule . module ) ;
735738 }
736739
737740 load . status = 'linked' ;
@@ -759,6 +762,7 @@ function logloads(loads) {
759762 * module.module bound module object
760763 * module.execute execution function for module
761764 * module.dependencies list of module objects for dependencies
765+ * See getOrCreateModuleRecord for all properties
762766 *
763767 */
764768 function doExecute ( module ) {
@@ -787,7 +791,7 @@ function logloads(loads) {
787791 var deps = module . dependencies ;
788792 var err ;
789793
790- for ( var i = 0 ; i < deps . length ; i ++ ) {
794+ for ( var i = 0 , l = deps . length ; i < l ; i ++ ) {
791795 var dep = deps [ i ] ;
792796 if ( indexOf . call ( seen , dep ) == - 1 ) {
793797 err = ensureEvaluated ( dep , seen , loader ) ;
@@ -807,7 +811,13 @@ function logloads(loads) {
807811 err = doExecute ( module ) ;
808812 if ( err )
809813 module . failed = true ;
810- module . module = _newModule ( module . exports ) ;
814+
815+ // spec variation
816+ // we don't create a new module here because it was created and ammended
817+ // we just disable further extensions instead
818+ if ( Object . preventExtensions )
819+ Object . preventExtensions ( module . module ) ;
820+
811821 module . execute = undefined ;
812822 return err ;
813823 }
0 commit comments