@@ -38,10 +38,8 @@ component output="false" {
3838 // placeholder for return value
3939 variables .routes = [];
4040
41- // Performance indexes for faster route matching.
42- // routeIndex: maps HTTP method -> array of routes for that method.
41+ // Performance index for faster route matching.
4342 // staticRoutes: maps "METHOD:/path" -> route struct for routes with no variables (O(1) lookup).
44- variables .routeIndex = {};
4543 variables .staticRoutes = {};
4644
4745 return this ;
@@ -132,9 +130,7 @@ component output="false" {
132130 /**
133131 * Private internal function.
134132 * Add route to Wheels, removing useless params.
135- * Also builds performance indexes for faster route matching:
136- * - routeIndex: Routes indexed by HTTP method (reduces search space)
137- * - staticRoutes: Hash map for routes with no variables (O(1) lookup)
133+ * Also builds a static route index for O(1) lookup of routes with no variables.
138134 */
139135 private void function $addRoute (required string pattern , required struct constraints ) {
140136 // Remove controller and action if they are route variables.
@@ -159,40 +155,32 @@ component output="false" {
159155 // Static routes can be matched via O(1) hash lookup instead of regex scanning.
160156 arguments .isStatic = ! Find (" [" , arguments .pattern );
161157
162- // Add route to Wheels.
163- ArrayAppend (variables .routes , arguments );
164- ArrayAppend (application [$appKey ()].routes , arguments );
165-
166- // Build method-indexed lookup for faster matching.
167- // This allows $findMatchingRoute to only scan routes for the requested HTTP method.
168- if (StructKeyExists (arguments , " methods" )) {
169- local .methodList = ListToArray (arguments .methods );
170- } else {
171- // If no method restriction, index under all methods.
172- local .methodList = [" get" , " post" , " put" , " patch" , " delete" , " head" ];
173- }
158+ // Create a plain struct copy of the route data. On Adobe CF, the arguments
159+ // scope is a special struct type that can cause Duplicate() failures when
160+ // stored in shared scopes and later deep-copied. StructCopy() produces a
161+ // plain CFML struct that is safe to Duplicate() on all engines.
162+ local .routeStruct = StructCopy (arguments );
174163
175- for (local .method in local .methodList ) {
176- local .methodKey = UCase (local .method );
164+ // Add route to Wheels.
165+ ArrayAppend (variables .routes , local .routeStruct );
166+ ArrayAppend (application [$appKey ()].routes , local .routeStruct );
177167
178- // Initialize route index and static route map in application scope if needed.
179- if (! StructKeyExists (application [$appKey ()], " routeIndex" )) {
180- application [$appKey ()].routeIndex = {};
181- }
168+ // Build static route index for O(1) lookup of routes with no variables.
169+ if (local .routeStruct .isStatic ) {
182170 if (! StructKeyExists (application [$appKey ()], " staticRoutes" )) {
183171 application [$appKey ()].staticRoutes = {};
184172 }
185173
186- if (! StructKeyExists (application [$appKey ()].routeIndex , local .methodKey )) {
187- application [$appKey ()].routeIndex [local .methodKey ] = [];
174+ if (StructKeyExists (local .routeStruct , " methods" )) {
175+ local .methodList = ListToArray (local .routeStruct .methods );
176+ } else {
177+ local .methodList = [" get" , " post" , " put" , " patch" , " delete" , " head" ];
188178 }
189- ArrayAppend (application [$appKey ()].routeIndex [local .methodKey ], arguments );
190179
191- // Add to static route fast-path index.
192- if (arguments .isStatic ) {
193- local .staticKey = local .methodKey & " :" & arguments .pattern ;
180+ for (local .method in local .methodList ) {
181+ local .staticKey = UCase (local .method ) & " :" & local .routeStruct .pattern ;
194182 if (! StructKeyExists (application [$appKey ()].staticRoutes , local .staticKey )) {
195- application [$appKey ()].staticRoutes [local .staticKey ] = arguments ;
183+ application [$appKey ()].staticRoutes [local .staticKey ] = local . routeStruct ;
196184 }
197185 }
198186 }
0 commit comments