next.js
8f1f03b3 - Resolve route interception problem with (..)(..) (#69012)

Commit
2 years ago
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>
Author
Parents
Loading