@@ -15,6 +15,13 @@ type HandlerParamsSet<T> = HandlerSet<T> & {
1515
1616const emptyParams = Object . create ( null )
1717
18+ const hasChildren = ( children : Record < string , unknown > ) : boolean => {
19+ for ( const _ in children ) {
20+ return true
21+ }
22+ return false
23+ }
24+
1825export class Node < T > {
1926 #methods: Record < string , HandlerSet < T > > [ ]
2027
@@ -77,13 +84,13 @@ export class Node<T> {
7784 return curNode
7885 }
7986
80- #getHandlerSets(
87+ #pushHandlerSets(
88+ handlerSets : HandlerParamsSet < T > [ ] ,
8189 node : Node < T > ,
8290 method : string ,
8391 nodeParams : Record < string , string > ,
8492 params ?: Record < string , string >
85- ) : HandlerParamsSet < T > [ ] {
86- const handlerSets : HandlerParamsSet < T > [ ] = [ ]
93+ ) : void {
8794 for ( let i = 0 , len = node . #methods. length ; i < len ; i ++ ) {
8895 const m = node . #methods[ i ]
8996 const handlerSet = ( m [ method ] || m [ METHOD_NAME_ALL ] ) as HandlerParamsSet < T >
@@ -102,7 +109,6 @@ export class Node<T> {
102109 }
103110 }
104111 }
105- return handlerSets
106112 }
107113
108114 search ( method : string , path : string ) : [ [ T , Params ] [ ] ] {
@@ -115,7 +121,10 @@ export class Node<T> {
115121 const parts = splitPath ( path )
116122 const curNodesQueue : Node < T > [ ] [ ] = [ ]
117123
118- for ( let i = 0 , len = parts . length ; i < len ; i ++ ) {
124+ const len = parts . length
125+ let partOffsets : number [ ] | null = null
126+
127+ for ( let i = 0 ; i < len ; i ++ ) {
119128 const part : string = parts [ i ]
120129 const isLast = i === len - 1
121130 const tempNodes : Node < T > [ ] = [ ]
@@ -129,11 +138,9 @@ export class Node<T> {
129138 if ( isLast ) {
130139 // '/hello/*' => match '/hello'
131140 if ( nextNode . #children[ '*' ] ) {
132- handlerSets . push (
133- ...this . #getHandlerSets( nextNode . #children[ '*' ] , method , node . #params)
134- )
141+ this . #pushHandlerSets( handlerSets , nextNode . #children[ '*' ] , method , node . #params)
135142 }
136- handlerSets . push ( ... this . #getHandlerSets ( nextNode , method , node . #params) )
143+ this . #pushHandlerSets ( handlerSets , nextNode , method , node . #params)
137144 } else {
138145 tempNodes . push ( nextNode )
139146 }
@@ -148,7 +155,7 @@ export class Node<T> {
148155 if ( pattern === '*' ) {
149156 const astNode = node . #children[ '*' ]
150157 if ( astNode ) {
151- handlerSets . push ( ... this . #getHandlerSets ( astNode , method , node . #params) )
158+ this . #pushHandlerSets ( handlerSets , astNode , method , node . #params)
152159 astNode . #params = params
153160 tempNodes . push ( astNode )
154161 }
@@ -164,14 +171,23 @@ export class Node<T> {
164171 const child = node . #children[ key ]
165172
166173 // `/js/:filename{[a-z]+.js}` => match /js/chunk/123.js
167- const restPathString = parts . slice ( i ) . join ( '/' )
168174 if ( matcher instanceof RegExp ) {
175+ if ( partOffsets === null ) {
176+ partOffsets = new Array ( len )
177+ let offset = path [ 0 ] === '/' ? 1 : 0
178+ for ( let p = 0 ; p < len ; p ++ ) {
179+ partOffsets [ p ] = offset
180+ offset += parts [ p ] . length + 1
181+ }
182+ }
183+ const restPathString = path . substring ( partOffsets [ i ] )
184+
169185 const m = matcher . exec ( restPathString )
170186 if ( m ) {
171187 params [ name ] = m [ 0 ]
172- handlerSets . push ( ... this . #getHandlerSets ( child , method , node . #params, params ) )
188+ this . #pushHandlerSets ( handlerSets , child , method , node . #params, params )
173189
174- if ( Object . keys ( child . #children) . length ) {
190+ if ( hasChildren ( child . #children) ) {
175191 child . #params = params
176192 const componentCount = m [ 0 ] . match ( / \/ / ) ?. length ?? 0
177193 const targetCurNodes = ( curNodesQueue [ componentCount ] ||= [ ] )
@@ -185,10 +201,14 @@ export class Node<T> {
185201 if ( matcher === true || matcher . test ( part ) ) {
186202 params [ name ] = part
187203 if ( isLast ) {
188- handlerSets . push ( ... this . #getHandlerSets ( child , method , params , node . #params) )
204+ this . #pushHandlerSets ( handlerSets , child , method , params , node . #params)
189205 if ( child . #children[ '*' ] ) {
190- handlerSets . push (
191- ...this . #getHandlerSets( child . #children[ '*' ] , method , params , node . #params)
206+ this . #pushHandlerSets(
207+ handlerSets ,
208+ child . #children[ '*' ] ,
209+ method ,
210+ params ,
211+ node . #params
192212 )
193213 }
194214 } else {
@@ -199,7 +219,8 @@ export class Node<T> {
199219 }
200220 }
201221
202- curNodes = tempNodes . concat ( curNodesQueue . shift ( ) ?? [ ] )
222+ const shifted = curNodesQueue . shift ( )
223+ curNodes = shifted ? tempNodes . concat ( shifted ) : tempNodes
203224 }
204225
205226 if ( handlerSets . length > 1 ) {
0 commit comments