Repository navigation
Open
Description
Why this matters (impact)
- Developer trust depends on clear and accurate claims — "zero dependencies" is a major selling point.
- Hidden runtime dependencies alter installation and bundling expectations (some toolchains need
@babel/runtimeinstalled explicitly). - Marketing and documentation inconsistency can negatively affect adoption.
This script programmatically demonstrates the inconsistency (it checks package.json and scans dist for @babel/runtime):
// (trimmed for brevity here; see file in repo for full script)
// It prints: package dependencies, whether dist files contain "@babel/runtime",
// and the observed website claim vs. actual.Run: node poc-zero-deps-mismatch.js
Tests (full contents included)
I added/used the following tests :
src/build.no-runtime-deps.test.ts— ensures no@babel/runtimestrings indistJS files
import fs from "fs";
import path from "path";
describe("packaging: runtime dependency consistency", () => {
it("should not contain @babel/runtime references in dist (claim: Zero dependencies)", () => {
const distDir = path.resolve(__dirname, "..", "dist");
const files = fs.readdirSync(distDir).filter((f) => f.endsWith(".js"));
const offending: string[] = [];
for (const f of files) {
const content = fs.readFileSync(path.join(distDir, f), "utf8");
if (content.indexOf("@babel/runtime") !== -1) offending.push(f);
}
expect(offending).toHaveLength(0);
});
});src/security.prototype-pollution.test.ts— defensive security test ensuring malicious field names cannot pollute prototypes
import { createForm } from "./index";
describe("security: prototype pollution", () => {
beforeEach(() => {
delete (Object.prototype as any).__polluted_by_test;
delete (Object.prototype as any).polluted;
});
it("should not allow prototype pollution via __proto__ path", () => {
const form = createForm({ onSubmit: () => {} });
// @ts-ignore - intentional malicious key simulation
form.change("__proto__.polluted", "yes");
expect(({} as any).polluted).toBeUndefined();
expect((Object.prototype as any).polluted).toBeUndefined();
});
it("should not allow prototype pollution via constructor.prototype path", () => {
const form = createForm({ onSubmit: () => {} });
// @ts-ignore
form.change("constructor.prototype.__polluted_by_test", "yes");
expect(({} as any).__polluted_by_test).toBeUndefined();
expect((Object.prototype as any).__polluted_by_test).toBeUndefined();
});
});Build & Test Evidence (what I ran locally)
- PoC run:
node poc-zero-deps-mismatch.js— report printed showing no runtime deps after the inlining fix.- Test suites: 26 total
- Passed: 25
- Failed: 1 (unrelated test:
src/FinalForm.validating.test.tsshows a timing/race expectation mismatch) - Tests: 341 passed, 1 failed (total 342)
Fix Options & Recommendation
A) Inline Babel helpers at build time (implemented in branch fix/zero-deps-mismatch):
- Change Babel helper behavior to
babelHelpers: 'bundled'inrollup.config.mjsand remove@babel/plugin-transform-runtime. - Remove
@babel/runtimefrom runtimedependenciesinpackage.json. - Pros: Restores true "Zero dependencies" for consumers, keeps website claim valid.
- Cons: Slight increase in minified bundle size (roughly +2KB minified; gzipped similar), but overall still small.
B) Update website/README to clarify/remove the "Zero dependencies" claim:
- Simpler and non-invasive: change documentation and website copy to reflect reality.
- Cons: Undermines original promise and may disappoint users who chose the package specifically for zero deps.
Files added/changed while investigating (local branch: fix/zero-deps-mismatch)
- Modified:
rollup.config.mjs(changedbabelHelpersfromruntimetobundled, removed@babel/plugin-transform-runtimeentry). - Modified:
package.json(removed@babel/runtimefromdependencies). - Added:
src/build.no-runtime-deps.test.ts(regression test to catch future regressions). - Added:
src/security.prototype-pollution.test.ts(security test for prototype pollution attack vectors).
Metadata
Metadata
Assignees
Labels
No labels
Activity