Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
- Adds `arrConcat` as a dedicated array helper and `fnBindArgs` as a dedicated function helper
- Improves function binding typing with exported `BoundFunction` and updated signatures for `fnBind` / `fnBindArgs`

### Bug Fixes

- [#568](https://github.com/nevware21/ts-utils/issues/568) Rolldown `INVALID_ANNOTATION` warnings caused by non-canonical PURE annotation spacing in generated output
- [#569](https://github.com/nevware21/ts-utils/pull/569) Add generated-chunk PURE annotation normalization so spaced forms are rewritten to canonical `(/*#__PURE__*/` / `(/*@__PURE__*/` in rollup output
- [#575](https://github.com/nevware21/ts-utils/pull/575) Add packaged artifact validation for PURE annotation spacing and update normalization tolerance, with per-file logging while scanning `lib/bundle` and `lib/dist`

# v0.14.0 May 18th, 2026

## Changelog
Expand Down
2 changes: 1 addition & 1 deletion lib/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export function uglify3(options = {}) {
// canonical form with the comment flush against the open paren, which every
// bundler accepts. Uses magic-string so the generated sourcemap stays valid.
export function fixPureAnnotations() {
const pureRe = /\([ \t]*\/\*[ \t]*([#@])__PURE__[ \t]*\*\//g;
const pureRe = /\(\s{0,5}\/\*\s{0,5}([#@])__PURE__\s{0,5}\*\//g;

return {
name: "fix-pure-annotations",
Expand Down
79 changes: 79 additions & 0 deletions lib/test/bundle-pure-annotations-check.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
const fs = require("fs");
const path = require("path");

const outputRoots = [
path.join(__dirname, "../bundle"),
path.join(__dirname, "../dist")
];

const invalidPureAnnotationRe = /\(\s+\/\*\s*([#@])__PURE__\s*\*\//g;

function collectJsFiles(rootPath, output) {
if (!fs.existsSync(rootPath)) {
return;
}

fs.readdirSync(rootPath).forEach((name) => {
const fullPath = path.join(rootPath, name);
const stat = fs.statSync(fullPath);

if (stat.isDirectory()) {
collectJsFiles(fullPath, output);
return;
}

if (stat.isFile() && path.extname(name) === ".js") {
output.push(fullPath);
}
});
}

function getLineNumber(content, index) {
let line = 1;
for (let lp = 0; lp < index; lp++) {
if (content.charCodeAt(lp) === 10) {
line++;
}
}

return line;
}

const jsFiles = [];
outputRoots.forEach((rootPath) => collectJsFiles(rootPath, jsFiles));

if (jsFiles.length === 0) {
console.error("No generated JavaScript files were found under lib/bundle or lib/dist");
process.exit(1);
}

const failures = [];

console.log("Scanning generated JavaScript files for PURE annotation spacing...");
console.log("Files discovered: " + jsFiles.length);

jsFiles.forEach((filePath) => {
const relativeFilePath = path.relative(process.cwd(), filePath).replace(/\\/g, "/");
console.log(" - Processing " + relativeFilePath);
const content = fs.readFileSync(filePath, "utf8");
let match;

invalidPureAnnotationRe.lastIndex = 0;
while ((match = invalidPureAnnotationRe.exec(content))) {
failures.push({
filePath: relativeFilePath,
line: getLineNumber(content, match.index),
sample: match[0]
});
}
});

if (failures.length > 0) {
console.error("Found invalid PURE annotations with leading whitespace after '(':");
failures.forEach((failure) => {
console.error(" - " + failure.filePath + ":" + failure.line + " -> " + failure.sample);
});
process.exit(1);
}

console.log("PURE annotation spacing check passed for generated bundle/dist JavaScript files.");
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@
"dtsgen": "api-extractor run --local --verbose && node lib/scripts/setTsReferences.js",
"size": "size-limit",
"size-save": "size-limit --clean-dir --save-bundle build/size",
"size-check": "node lib/test/bundle-size-check.js",
"size-check": "node lib/test/bundle-size-check.js && node lib/test/bundle-pure-annotations-check.js",
"link-check": "node lib/test/readme-links-check.js",
"readme-link-check": "npm run docs && npm run link-check"
},
Expand Down