Resolve route interception problem with (..)(..) (#69012)
fixes #57016
### WHAT?
Route interception with segments two levels above is not working
correctly.
### WHY?
Details are provided here:
https://github.com/vercel/next.js/issues/57016#issuecomment-1769275539
### HOW?
When the marker is `'(..)(..)'`, setting:
```
if (marker === '(..)(..)') {
args.params['0'] = '(..)'
args.params['1'] = '(..)'
} else {
args.params['0'] = marker
}
```
helps prevent the bug that occurs with:
```
var value = data ? data[token.name] : undefined;
```
(tokensToFunction in next/dist/compiled/path-to-regexp/index.js)
For example, if the tokens passed to tokensToFunction are:
```
[
'/foo/bar',
{ name: 0, prefix: '/', suffix: '', pattern: '..', modifier: '' },
{ name: 1, prefix: '', suffix: '', pattern: '..', modifier: '' },
'fizz'
]
```
then the data in function(data) will be:
```
{ '0': '(..)', '1': '(..)' }
```
allowing you to access data['1'] without errors with:
```
var value = data ? data[token.name] : undefined;
```
This method also minimizes the impact on existing code.
tokensToFunction in `next/dist/compiled/path-to-regexp/index.js`
<details>
```
/**
* Compile a string to a template function for the path.
*/
function compile(str, options) {
return tokensToFunction(parse(str, options), options);
}
exports.compile = compile;
/**
* Expose a method for transforming tokens into the path function.
*/
function tokensToFunction(tokens, options) {
if (options === void 0) { options = {}; }
var reFlags = flags(options);
var _a = options.encode, encode = _a === void 0 ? function (x) { return x; } : _a, _b = options.validate, validate = _b === void 0 ? true : _b;
// Compile all the tokens into regexps.
var matches = tokens.map(function (token) {
if (typeof token === "object") {
return new RegExp("^(?:" + token.pattern + ")$", reFlags);
}
});
return function (data) {
var path = "";
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (typeof token === "string") {
path += token;
continue;
}
var value = data ? data[token.name] : undefined;
var optional = token.modifier === "?" || token.modifier === "*";
var repeat = token.modifier === "*" || token.modifier === "+";
if (Array.isArray(value)) {
if (!repeat) {
throw new TypeError("Expected \"" + token.name + "\" to not repeat, but got an array");
}
if (value.length === 0) {
if (optional)
continue;
throw new TypeError("Expected \"" + token.name + "\" to not be empty");
}
for (var j = 0; j < value.length; j++) {
var segment = encode(value[j], token);
if (validate && !matches[i].test(segment)) {
throw new TypeError("Expected all \"" + token.name + "\" to match \"" + token.pattern + "\", but got \"" + segment + "\"");
}
path += token.prefix + segment + token.suffix;
}
continue;
}
if (typeof value === "string" || typeof value === "number") {
var segment = encode(String(value), token);
if (validate && !matches[i].test(segment)) {
throw new TypeError("Expected \"" + token.name + "\" to match \"" + token.pattern + "\", but got \"" + segment + "\"");
}
path += token.prefix + segment + token.suffix;
continue;
}
if (optional)
continue;
var typeOfMessage = repeat ? "an array" : "a string";
throw new TypeError("Expected \"" + token.name + "\" to be " + typeOfMessage);
}
return path;
};
}
exports.tokensToFunction = tokensToFunction;
```
</details>