diff --git a/scripts/ci/validate-carrier-closure.js b/scripts/ci/validate-carrier-closure.js index cea037909..b6e4682db 100644 --- a/scripts/ci/validate-carrier-closure.js +++ b/scripts/ci/validate-carrier-closure.js @@ -26,12 +26,14 @@ const BUILTINS = new Set(builtinModules); const SCRIPT_EXTENSIONS = new Set(['.js', '.cjs', '.mjs']); const MARK = '\u0000'; const SLOT = `${MARK}(\\d+)${MARK}`; -const CALL_PATTERN = new RegExp(`\\b(require|import)\\s*\\(\\s*${SLOT}\\s*\\)`, 'g'); +// `obj.require(`, `obj?.import(` and `obj . require(` are method calls, not module loads. +const NOT_MEMBER = '(? { + const start = match.index + match[0].length; + let depth = 1; + let cursor = start; + while (cursor < code.length && depth > 0) { + if (code[cursor] === '(') depth += 1; + else if (code[cursor] === ')') depth -= 1; + cursor += 1; + } + if (depth === 0) found.push(code.slice(start, cursor - 1).trim()); + }); + return found; +} + function renderExpression(text, literals) { return text.replace(SLOT_PATTERN, (_whole, slotIndex) => `'${literals[Number(slotIndex)]}'`).split(CLOSE).join(' ').trim(); } @@ -220,11 +243,10 @@ function extractReferences(rawSource) { collect(SLOT_PATTERN, match[1], slotMatch => segments.push(literals[Number(slotMatch[1])])); specifiers.add(`./${segments.join('/')}`); }); - collect(DYNAMIC_PATTERN, code, match => { - const argument = match[1].trim(); - if (new RegExp(`^${SLOT}$`).test(argument) || STATIC_JOIN_PATTERN.test(argument)) return; + for (const argument of callArguments(code)) { + if (!argument || new RegExp(`^${SLOT}$`).test(argument) || STATIC_JOIN_PATTERN.test(argument)) continue; dynamic.add(renderExpression(argument, literals)); - }); + } return { specifiers: [...specifiers], imports: [...imports], packages: [...packages], dynamic: [...dynamic] }; }