diff --git a/Makefile b/Makefile index 67000b141c..2b5eacda9f 100644 --- a/Makefile +++ b/Makefile @@ -696,6 +696,14 @@ compat-table: esbuild | compat-table/node_modules ./esbuild compat-table/src/index.ts --bundle --platform=node --external:./compat-table/repos/* --outfile=compat-table/out.js --log-level=warning --sourcemap node --enable-source-maps compat-table/out.js +check-compat-table: compat-table + @if ! git diff --quiet internal/compat/js_table.go internal/compat/css_table.go 2>/dev/null; then \ + echo "ERROR: Compat tables are out of date. Run 'make compat-table' and commit the changes."; \ + git diff --stat internal/compat/js_table.go internal/compat/css_table.go; \ + exit 1; \ + fi + @echo "Compat tables are up to date." + update-compat-table: esbuild cd compat-table && npm i @mdn/browser-compat-data@latest caniuse-lite@latest --silent --save-exact ./esbuild compat-table/src/index.ts --bundle --platform=node --external:./compat-table/repos/* --outfile=compat-table/out.js --log-level=warning --sourcemap diff --git a/internal/compat/compat_test.go b/internal/compat/compat_test.go index 8e1cbee598..11b6c06187 100644 --- a/internal/compat/compat_test.go +++ b/internal/compat/compat_test.go @@ -61,3 +61,18 @@ func TestCompareVersions(t *testing.T) { check(v{1, 2, 3}, Semver{Parts: []int{1, 2, 3}, PreRelease: "-pre"}, '>') check(v{1, 2, 2}, Semver{Parts: []int{1, 2, 3}, PreRelease: "-pre"}, '<') } + +func TestFeatureLimits(t *testing.T) { + // The bitmask for JSFeature is uint64, which means it can only hold up to 64 flags. + // If this limit is exceeded, compilation will fail due to the compile-time guard in + // js_table.go, but this test provides a clearer error message. + if len(jsTable) > 64 { + t.Errorf("JSFeature capacity exceeded (max 64, got %d)", len(jsTable)) + } + + // The bitmask for CSSFeature is uint16, which means it can only hold up to 16 flags. + if len(cssTable) > 16 { + t.Errorf("CSSFeature capacity exceeded (max 16, got %d)", len(cssTable)) + } +} + diff --git a/internal/compat/js_table.go b/internal/compat/js_table.go index 0a4ff9c312..6d8b547b92 100644 --- a/internal/compat/js_table.go +++ b/internal/compat/js_table.go @@ -121,8 +121,17 @@ const ( TypeofExoticObjectIsObject UnicodeEscapes Using + + // WARNING: JSFeature is a uint64 bitmask. As of this writing, 61 of 64 bits are + // used (only 3 remaining). If more features are needed, the type must be widened + // or the representation changed. ) +// Compile-time assertion: fails if the number of JSFeature values reaches 64. +// When the last iota equals 63, Using would be 1<<63 and doubling it overflows +// uint64, causing a compile error. When iota reaches 64, the shift overflows to 0. +const _ = uint64(Using) * 2 + var StringToJSFeature = map[string]JSFeature{ "arbitrary-module-namespace-names": ArbitraryModuleNamespaceNames, "array-spread": ArraySpread,