diff --git a/.github/check_corejs.py b/.github/check_corejs.py new file mode 100644 index 00000000..3540b136 --- /dev/null +++ b/.github/check_corejs.py @@ -0,0 +1,46 @@ +"""Fail when a shipped JavaScript bundle contains core-js older than 3.3.5. + +Older core-js runs feature checks that write `constructor` on a real RegExp and +Promise. In V8 (Chrome, Edge) that write turns off the RegExp and Promise fast +paths for the whole page. After that, String#split, #match, #replace and +#search with a RegExp are up to 80 times slower, also in other libraries on +the page. core-js 3.3.4 and 3.3.5 fixed this (zloirock/core-js#306, #679). + +Usage: python .github/check_corejs.py FILE... +""" + +import re +import sys +from pathlib import Path + +MINIMUM = (3, 3, 5) +# core-js registers itself in a shared store: {version:"3.1.3",mode:"global",...} +MARKER = re.compile(rb"""version\s*:\s*["'](\d+)\.(\d+)\.(\d+)["']\s*,\s*mode\s*:""") + + +def main(paths): + if not paths: + print("error: no bundles given") + return 1 + failed = False + for path in paths: + file = Path(path) + if not file.is_file(): + print(f"error: {path}: file not found") + failed = True + continue + found = { + tuple(int(part) for part in m.groups()) for m in MARKER.finditer(file.read_bytes()) + } + names = ", ".join(".".join(map(str, version)) for version in sorted(found)) or "none" + old = [version for version in found if version < MINIMUM] + if old: + failed = True + print(f"error: {path}: core-js {names}, older than 3.3.5") + else: + print(f"ok: {path}: core-js {names}") + return 1 if failed else 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ff9f1479..8f229c8e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,6 +9,12 @@ on: pull_request: workflow_dispatch: +env: + # npm dist-tag for releases from this branch. npm's "latest" tag belongs to the + # newest major (3.x); a 1.x release with "latest" would move it back to 1.x. + # npm rejects a tag that looks like a semver range (such as "1.x"). + NPM_TAG: latest-1 + jobs: lint: runs-on: ubuntu-24.04 @@ -26,19 +32,23 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.10" - # https://github.com/webpack/webpack/issues/14532 + # The build backend installs the newest jupyterlab 4.x, whose labextension + # builder needs Node.js ^20.19.0 || >=22.12.0. - uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 22 - name: install build run: python -m pip install build - name: Install dependencies run: | python -m pip install --upgrade pip - pip install "reacton[generate]" ipyvue + pip install "reacton[generate]" "ipyvue>=1.7,<2" - name: build wheel run: python -m build + - name: Check the core-js version in the bundles + # core-js older than 3.3.5 turns off V8's RegExp fast paths for the whole page. + run: python .github/check_corejs.py prefix/share/jupyter/nbextensions/jupyter-vuetify/*.js prefix/share/jupyter/labextensions/jupyter-vuetify/static/*.js js/dist/*.js - name: Build component file run: | @@ -140,12 +150,9 @@ jobs: - name: Publish the NPM package run: | cd js - echo $PRE_RELEASE - if [[ $PRE_RELEASE == "true" ]]; then export TAG="next"; else export TAG="latest"; fi - npm publish --dry-run --tag ${TAG} --access public *.tgz + npm publish --dry-run --tag "$NPM_TAG" --access public *.tgz env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - PRE_RELEASE: ${{ github.event.release.prerelease }} release: if: startsWith(github.event.ref, 'refs/tags/v') @@ -181,9 +188,6 @@ jobs: - name: Publish the NPM package run: | cd js - echo $PRE_RELEASE - if [[ $PRE_RELEASE == "true" ]]; then export TAG="next"; else export TAG="latest"; fi - npm publish --tag ${TAG} --access public *.tgz + npm publish --tag "$NPM_TAG" --access public *.tgz env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - PRE_RELEASE: ${{ github.event.release.prerelease }} diff --git a/js/package-lock.json b/js/package-lock.json index 5fbd514a..6b2baffc 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -13,7 +13,7 @@ "@jupyterlab/apputils": "^2 || ^3 || ^4", "@mariobuikhuizen/vuetify": "2.2.26-rc.1", "@mdi/font": "^4.9.95", - "core-js": "^3.0.1", + "core-js": "^3.50.0", "jupyter-vue": "^1.11.2", "lodash": "^4.17.11", "material-design-icons-iconfont": "^5.0.1", @@ -3503,10 +3503,18 @@ } }, "node_modules/core-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", - "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js." + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.50.0.tgz", + "integrity": "sha512-BRWgOLKkFeCgRudR6zrs8p9XJZcE14grzKMMssoYrk6krtuEZ7MTKPIY5RzOnqsEKIR9kst7wNzphttraT+Yqw==", + "hasInstallScript": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } }, "node_modules/core-js-compat": { "version": "3.0.1", @@ -3520,6 +3528,14 @@ "semver": "^6.0.0" } }, + "node_modules/core-js-compat/node_modules/core-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", + "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "license": "MIT" + }, "node_modules/core-js-compat/node_modules/semver": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", @@ -12785,9 +12801,9 @@ "optional": true }, "core-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", - "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==" + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.50.0.tgz", + "integrity": "sha512-BRWgOLKkFeCgRudR6zrs8p9XJZcE14grzKMMssoYrk6krtuEZ7MTKPIY5RzOnqsEKIR9kst7wNzphttraT+Yqw==" }, "core-js-compat": { "version": "3.0.1", @@ -12801,6 +12817,12 @@ "semver": "^6.0.0" }, "dependencies": { + "core-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", + "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", + "dev": true + }, "semver": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", diff --git a/js/package.json b/js/package.json index 4ec504ab..f7577cc9 100755 --- a/js/package.json +++ b/js/package.json @@ -60,7 +60,7 @@ "@jupyterlab/apputils": "^2 || ^3 || ^4", "@mariobuikhuizen/vuetify": "2.2.26-rc.1", "@mdi/font": "^4.9.95", - "core-js": "^3.0.1", + "core-js": "^3.50.0", "jupyter-vue": "^1.11.2", "lodash": "^4.17.11", "material-design-icons-iconfont": "^5.0.1",