Skip to content

Commit ed40df2

Browse files
committed
WIP: v8
1 parent f5a99b0 commit ed40df2

File tree

6 files changed

+129
-258
lines changed

6 files changed

+129
-258
lines changed

index.js

+7-9
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,6 @@ function processParams (params, layer, called, req, res, done) {
576576
}
577577

578578
let i = 0
579-
let name
580579
let paramIndex = 0
581580
let key
582581
let paramVal
@@ -596,10 +595,9 @@ function processParams (params, layer, called, req, res, done) {
596595

597596
paramIndex = 0
598597
key = keys[i++]
599-
name = key.name
600-
paramVal = req.params[name]
601-
paramCallbacks = params[name]
602-
paramCalled = called[name]
598+
paramVal = req.params[key]
599+
paramCallbacks = params[key]
600+
paramCalled = called[key]
603601

604602
if (paramVal === undefined || !paramCallbacks) {
605603
return param()
@@ -609,13 +607,13 @@ function processParams (params, layer, called, req, res, done) {
609607
if (paramCalled && (paramCalled.match === paramVal ||
610608
(paramCalled.error && paramCalled.error !== 'route'))) {
611609
// restore value
612-
req.params[name] = paramCalled.value
610+
req.params[key] = paramCalled.value
613611

614612
// next param
615613
return param(paramCalled.error)
616614
}
617615

618-
called[name] = paramCalled = {
616+
called[key] = paramCalled = {
619617
error: null,
620618
match: paramVal,
621619
value: paramVal
@@ -629,7 +627,7 @@ function processParams (params, layer, called, req, res, done) {
629627
const fn = paramCallbacks[paramIndex++]
630628

631629
// store updated value
632-
paramCalled.value = req.params[key.name]
630+
paramCalled.value = req.params[key]
633631

634632
if (err) {
635633
// store error
@@ -641,7 +639,7 @@ function processParams (params, layer, called, req, res, done) {
641639
if (!fn) return param()
642640

643641
try {
644-
const ret = fn(req, res, paramCallback, paramVal, key.name)
642+
const ret = fn(req, res, paramCallback, paramVal, key)
645643
if (isPromise(ret)) {
646644
ret.then(null, function (error) {
647645
paramCallback(error || new Error('Rejected promise'))

lib/layer.js

+58-23
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const pathRegexp = require('path-to-regexp')
2222

2323
const hasOwnProperty = Object.prototype.hasOwnProperty
2424
const TRAILING_SLASH_REGEXP = /\/+$/
25+
const MATCHING_GROUP_REGEXP = /\((?:\?<(.*?)>)?(?!\?)/g
2526

2627
/**
2728
* Expose `Layer`.
@@ -41,10 +42,53 @@ function Layer (path, options, fn) {
4142
this.name = fn.name || '<anonymous>'
4243
this.params = undefined
4344
this.path = undefined
44-
this.regexp = pathRegexp((opts.strict ? path : loosen(path)), this.keys, opts)
45+
this.slash = path === '/' && opts.end === false
46+
47+
function matcher (_path) {
48+
if (_path instanceof RegExp) {
49+
const keys = []
50+
let name = 0
51+
let m
52+
// eslint-disable-next-line no-cond-assign
53+
while (m = MATCHING_GROUP_REGEXP.exec(_path.source)) {
54+
keys.push({
55+
name: m[1] || name++,
56+
offset: m.index
57+
})
58+
}
59+
60+
return function regexpMatcher (p) {
61+
const match = _path.exec(p)
62+
if (!match) {
63+
return false
64+
}
65+
66+
const params = {}
67+
for (let i = 1; i < match.length; i++) {
68+
const key = keys[i - 1]
69+
const prop = key.name
70+
const val = decodeParam(match[i])
71+
72+
if (val !== undefined || !(hasOwnProperty.call(params, prop))) {
73+
params[prop] = val
74+
}
75+
}
76+
77+
return {
78+
params,
79+
path: p
80+
}
81+
}
82+
}
4583

46-
// set fast path flags
47-
this.regexp._slash = path === '/' && opts.end === false
84+
return pathRegexp.match((opts.strict ? _path : loosen(_path)), {
85+
sensitive: opts.sensitive,
86+
end: opts.end,
87+
trailing: !opts.strict,
88+
decode: decodeParam
89+
})
90+
}
91+
this.matchers = Array.isArray(path) ? path.map(matcher) : [matcher(path)]
4892
}
4993

5094
/**
@@ -126,14 +170,18 @@ Layer.prototype.match = function match (path) {
126170

127171
if (path != null) {
128172
// fast path non-ending match for / (any path matches)
129-
if (this.regexp._slash) {
173+
if (this.slash) {
130174
this.params = {}
131175
this.path = ''
132176
return true
133177
}
134178

135-
// match the path
136-
match = this.regexp.exec(path)
179+
let i = 0
180+
while (!match && i < this.matchers.length) {
181+
// match the path
182+
match = this.matchers[i](path)
183+
i++
184+
}
137185
}
138186

139187
if (!match) {
@@ -143,22 +191,9 @@ Layer.prototype.match = function match (path) {
143191
}
144192

145193
// store values
146-
this.params = {}
147-
this.path = match[0]
148-
149-
// iterate matches
150-
const keys = this.keys
151-
const params = this.params
152-
153-
for (let i = 1; i < match.length; i++) {
154-
const key = keys[i - 1]
155-
const prop = key.name
156-
const val = decodeParam(match[i])
157-
158-
if (val !== undefined || !(hasOwnProperty.call(params, prop))) {
159-
params[prop] = val
160-
}
161-
}
194+
this.params = match.params
195+
this.path = match.path
196+
this.keys = Object.keys(match.params)
162197

163198
return true
164199
}
@@ -192,7 +227,7 @@ function decodeParam (val) {
192227
* Loosens the given path for path-to-regexp matching.
193228
*/
194229
function loosen (path) {
195-
if (path instanceof RegExp) {
230+
if (path instanceof RegExp || path === '/') {
196231
return path
197232
}
198233

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"scripts": {
4242
"lint": "standard",
4343
"test": "mocha --reporter spec --bail --check-leaks test/",
44+
"test:debug": "mocha --reporter spec --bail --check-leaks test/ --inspect --inspect-brk",
4445
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
4546
"test-cov": "nyc --reporter=text npm test",
4647
"version": "node scripts/version-history.js && git add HISTORY.md"

test/req.params.js

-40
Original file line numberDiff line numberDiff line change
@@ -124,46 +124,6 @@ describe('req.params', function () {
124124
.expect('x-params-1', '{"foo":"buzz"}')
125125
.expect(200, '{"foo":"bar"}', done)
126126
})
127-
128-
describe('with numeric properties in req.params', function () {
129-
it('should merge numeric properties by offsetting', function (done) {
130-
const router = Router({ mergeParams: true })
131-
const server = createServer(function (req, res, next) {
132-
req.params = { 0: 'foo', 1: 'bar' }
133-
134-
router(req, res, function (err) {
135-
if (err) return next(err)
136-
sawParams(req, res)
137-
})
138-
})
139-
140-
router.get('/(.*)', hitParams(1))
141-
142-
request(server)
143-
.get('/buzz')
144-
.expect('x-params-1', '{"0":"foo","1":"bar","2":"buzz"}')
145-
.expect(200, '{"0":"foo","1":"bar"}', done)
146-
})
147-
148-
it('should merge with same numeric properties', function (done) {
149-
const router = Router({ mergeParams: true })
150-
const server = createServer(function (req, res, next) {
151-
req.params = { 0: 'foo' }
152-
153-
router(req, res, function (err) {
154-
if (err) return next(err)
155-
sawParams(req, res)
156-
})
157-
})
158-
159-
router.get('/(.*)', hitParams(1))
160-
161-
request(server)
162-
.get('/bar')
163-
.expect('x-params-1', '{"0":"foo","1":"bar"}')
164-
.expect(200, '{"0":"foo"}', done)
165-
})
166-
})
167127
})
168128
})
169129

0 commit comments

Comments
 (0)