@@ -124,6 +124,13 @@ function Namespace(name, options) {
124124 * @protected
125125 */
126126 this . _needsRecursiveFeatureResolution = true ;
127+
128+ /**
129+ * Whether or not objects contained in this namespace need a resolve.
130+ * @type {boolean }
131+ * @protected
132+ */
133+ this . _needsRecursiveResolve = true ;
127134}
128135
129136function clearCache ( namespace ) {
@@ -273,11 +280,13 @@ Namespace.prototype.add = function add(object) {
273280 }
274281
275282 this . _needsRecursiveFeatureResolution = true ;
283+ this . _needsRecursiveResolve = true ;
276284
277285 // Also clear parent caches, since they need to recurse down.
278286 var parent = this ;
279287 while ( parent = parent . parent ) {
280288 parent . _needsRecursiveFeatureResolution = true ;
289+ parent . _needsRecursiveResolve = true ;
281290 }
282291
283292 object . onAdd ( this ) ;
@@ -341,13 +350,16 @@ Namespace.prototype.define = function define(path, json) {
341350 * @returns {Namespace } `this`
342351 */
343352Namespace . prototype . resolveAll = function resolveAll ( ) {
353+ if ( ! this . _needsRecursiveResolve ) return this ;
354+
344355 var nested = this . nestedArray , i = 0 ;
345356 this . resolve ( ) ;
346357 while ( i < nested . length )
347358 if ( nested [ i ] instanceof Namespace )
348359 nested [ i ++ ] . resolveAll ( ) ;
349360 else
350361 nested [ i ++ ] . resolve ( ) ;
362+ this . _needsRecursiveResolve = false ;
351363 return this ;
352364} ;
353365
@@ -389,29 +401,47 @@ Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChe
389401 } else if ( ! path . length )
390402 return this ;
391403
404+ var flatPath = path . join ( "." ) ;
405+
392406 // Start at root if path is absolute
393407 if ( path [ 0 ] === "" )
394408 return this . root . lookup ( path . slice ( 1 ) , filterTypes ) ;
395409
396- var found = this . _lookupImpl ( path ) ;
410+ // Early bailout for objects with matching absolute paths
411+ var found = this . root . _fullyQualifiedObjects [ "." + flatPath ] ;
412+ if ( found && ( ! filterTypes || filterTypes . indexOf ( found . constructor ) > - 1 ) ) {
413+ return found ;
414+ }
415+
416+ // Do a regular lookup at this namespace and below
417+ found = this . _lookupImpl ( path , flatPath ) ;
397418 if ( found && ( ! filterTypes || filterTypes . indexOf ( found . constructor ) > - 1 ) ) {
398419 return found ;
399420 }
400421
401- // If there hasn't been a match, try again at the parent
402- if ( this . parent === null || parentAlreadyChecked )
422+ if ( parentAlreadyChecked )
403423 return null ;
404- return this . parent . lookup ( path , filterTypes ) ;
424+
425+ // If there hasn't been a match, walk up the tree and look more broadly
426+ var current = this ;
427+ while ( current . parent ) {
428+ found = current . parent . _lookupImpl ( path , flatPath ) ;
429+ if ( found && ( ! filterTypes || filterTypes . indexOf ( found . constructor ) > - 1 ) ) {
430+ return found ;
431+ }
432+ current = current . parent ;
433+ }
434+ return null ;
405435} ;
406436
407437/**
408438 * Internal helper for lookup that handles searching just at this namespace and below along with caching.
409439 * @param {string[] } path Path to look up
440+ * @param {string } flatPath Flattened version of the path to use as a cache key
410441 * @returns {ReflectionObject|null } Looked up object or `null` if none could be found
411442 * @private
412443 */
413- Namespace . prototype . _lookupImpl = function lookup ( path ) {
414- var flatPath = path . join ( "." ) ;
444+ Namespace . prototype . _lookupImpl = function lookup ( path , flatPath ) {
415445 if ( Object . prototype . hasOwnProperty . call ( this . _lookupCache , flatPath ) ) {
416446 return this . _lookupCache [ flatPath ] ;
417447 }
@@ -422,13 +452,15 @@ Namespace.prototype._lookupImpl = function lookup(path) {
422452 if ( found ) {
423453 if ( path . length === 1 ) {
424454 exact = found ;
425- } else if ( found instanceof Namespace && ( found = found . _lookupImpl ( path . slice ( 1 ) ) ) )
426- exact = found ;
455+ } else if ( found instanceof Namespace ) {
456+ path = path . slice ( 1 ) ;
457+ exact = found . _lookupImpl ( path , path . join ( "." ) ) ;
458+ }
427459
428460 // Otherwise try each nested namespace
429461 } else {
430462 for ( var i = 0 ; i < this . nestedArray . length ; ++ i )
431- if ( this . _nestedArray [ i ] instanceof Namespace && ( found = this . _nestedArray [ i ] . _lookupImpl ( path ) ) )
463+ if ( this . _nestedArray [ i ] instanceof Namespace && ( found = this . _nestedArray [ i ] . _lookupImpl ( path , flatPath ) ) )
432464 exact = found ;
433465 }
434466
0 commit comments