Compare commits

..
125 changed files with 1469 additions and 2685 deletions
+20 -36
View File
@@ -192,7 +192,7 @@
"zod": "catalog:",
},
"peerDependencies": {
"effect": "4.0.0-rc.112",
"effect": "4.0.0-rc.115",
"solid-js": ">=1.9.0",
},
"optionalPeers": [
@@ -367,7 +367,7 @@
"drizzle-orm": "catalog:",
"effect": "catalog:",
"fuzzysort": "3.1.0",
"gitlab-ai-provider": "6.16.0",
"gitlab-ai-provider": "6.12.1",
"google-auth-library": "10.5.0",
"gray-matter": "4.0.3",
"htmlparser2": "8.0.2",
@@ -403,6 +403,7 @@
"@types/node": "catalog:",
"@types/which": "3.0.4",
"drizzle-kit": "catalog:",
"fast-check": "catalog:",
},
},
"packages/desktop": {
@@ -511,7 +512,7 @@
"name": "@opencode/http-recorder",
"version": "2.0.14",
"dependencies": {
"@effect/platform-node-shared": "4.0.0-rc.112",
"@effect/platform-node-shared": "4.0.0-rc.115",
},
"devDependencies": {
"@effect/platform-node": "catalog:",
@@ -1099,10 +1100,10 @@
"catalog": {
"@cloudflare/workers-types": "4.20251008.0",
"@corvu/drawer": "0.2.4",
"@effect/opentelemetry": "4.0.0-rc.112",
"@effect/platform-node": "4.0.0-rc.112",
"@effect/platform-node-shared": "4.0.0-rc.112",
"@effect/sql-sqlite-bun": "4.0.0-rc.112",
"@effect/opentelemetry": "4.0.0-rc.115",
"@effect/platform-node": "4.0.0-rc.115",
"@effect/platform-node-shared": "4.0.0-rc.115",
"@effect/sql-sqlite-bun": "4.0.0-rc.115",
"@hono/standard-validator": "0.2.0",
"@hono/zod-validator": "0.4.2",
"@kobalte/core": "0.13.13",
@@ -1142,7 +1143,8 @@
"dompurify": "3.4.14",
"drizzle-kit": "1.0.0-rc.5-ab785fc",
"drizzle-orm": "1.0.0-rc.5-169397b",
"effect": "4.0.0-rc.112",
"effect": "4.0.0-rc.115",
"fast-check": "4.9.0",
"fuzzysort": "3.1.0",
"get-east-asian-width": "1.6.0",
"hono": "4.10.7",
@@ -1674,13 +1676,13 @@
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.12.0", "", {}, "sha512-mlUE+rZ8CatQekLhnaiN91Iemdd+e2gFKooGlnRB3oPTL3VghLfX24dx7HrzMNeC1JrIB/0kpsfyty3f5HNfxQ=="],
"@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-rc.112", "", { "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <2.0.0", "@opentelemetry/api-logs": ">=0.203.0 <0.300.0", "@opentelemetry/resources": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-base": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-node": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-web": ">=2.0.0 <3.0.0", "@opentelemetry/semantic-conventions": ">=1.33.0 <2.0.0", "effect": "^4.0.0-rc.112" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/api-logs", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-OTRv1DxTHUmnakgJ6XVM8wVgF1KgZH4UXnOemwSLUwUjXO+RCikzF8oR/rlVmOGq81KtQzj1URM4M4nchlQOuQ=="],
"@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-rc.115", "", { "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <2.0.0", "@opentelemetry/api-logs": ">=0.203.0 <0.300.0", "@opentelemetry/resources": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-base": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-node": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-web": ">=2.0.0 <3.0.0", "@opentelemetry/semantic-conventions": ">=1.33.0 <2.0.0", "effect": "^4.0.0-rc.115" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/api-logs", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-ITOqqf/Z0mrs6XhuV8wb4YYFt0sdMhXZGPtytr+YG87YG6mFdYkc8IaJj8cGQFKRkGota/2CN+zjBKhQVI64OQ=="],
"@effect/platform-node": ["@effect/platform-node@4.0.0-rc.112", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-rc.112", "mime": "^4.1.0", "undici": "^8.10.0" }, "peerDependencies": { "effect": "^4.0.0-rc.112", "redis": ">=5.0.0 <7.0.0" } }, "sha512-/BMAcdNGQQskLmI0Zoa95KfTZkr9HV9N4NSxaSrusG6GeW6Ulp9KvZ+Rlaiw8lnOt43CXjFLdfll5/k5rxL4hQ=="],
"@effect/platform-node": ["@effect/platform-node@4.0.0-rc.115", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-rc.115", "undici": "^8.10.2" }, "peerDependencies": { "effect": "^4.0.0-rc.115", "redis": ">=5.0.0 <7.0.0" } }, "sha512-mW03Wjq2FiTL5oi9yOkaKpCyUNBaduKgTk7qMHNELvC21Jq2qOAfdsfH+p+s2zmpB9w2RSa+ApODv4WjO9wQfw=="],
"@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-rc.112", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.21.3" }, "peerDependencies": { "effect": "^4.0.0-rc.112" } }, "sha512-ttjz0xKamFN7vL8pNDYVwddJLjZvqKePc05djlz2VcdaKbLsnYbtMnL1rbOfHgEnIUSHGh7FkjaN4DM1Ov81sQ=="],
"@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-rc.115", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.21.3" }, "peerDependencies": { "effect": "^4.0.0-rc.115" } }, "sha512-rcBwhDIfb82akJoTv7Vwh8K5x9vC/XfuePS7JjOr+z+dORXzsmKqI1BUQF27ARCN9fTAbDh7I6YvBlWhLjnqNg=="],
"@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-rc.112", "", { "peerDependencies": { "effect": "^4.0.0-rc.112" } }, "sha512-EqR8pWZo3VzedRvP6qo5HcfqNmFvSa+sQLWQl3oBMx2KY1FCc8NYjep79wYjNkW0qABnffrPUXCMTOncd1A+5g=="],
"@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-rc.115", "", { "peerDependencies": { "effect": "^4.0.0-rc.115" } }, "sha512-CypwmCPAUSOOhopcnSI9ocgpKHfpgOdERpei3GuXZm5cCGP31pk2NUETqNaYhonhr2bWd+6Rc8atctnEbIYKYQ=="],
"@electron-internal/extract-zip": ["@electron-internal/extract-zip@1.0.5", "", {}, "sha512-+bqFCP98pLI0Tt0XQo1TmlXtwjWchISndDOxCkEcIuUgXWpBnLyRI+2DU+mesvnMMX6L1XDqYNA0lXNDHd/yiA=="],
@@ -2014,18 +2016,6 @@
"@motionone/utils": ["@motionone/utils@10.18.0", "", { "dependencies": { "@motionone/types": "^10.17.1", "hey-listen": "^1.0.8", "tslib": "^2.3.1" } }, "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw=="],
"@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ=="],
"@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w=="],
"@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4", "", { "os": "linux", "cpu": "arm" }, "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw=="],
"@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw=="],
"@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ=="],
"@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4", "", { "os": "win32", "cpu": "x64" }, "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ=="],
"@napi-rs/lzma-linux-x64-gnu": ["@napi-rs/lzma-linux-x64-gnu@1.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ=="],
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.2.3", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" } }, "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q=="],
@@ -3878,7 +3868,7 @@
"editorconfig": ["editorconfig@1.0.7", "", { "dependencies": { "@one-ini/wasm": "0.1.1", "commander": "^10.0.0", "minimatch": "^9.0.1", "semver": "^7.5.3" }, "bin": { "editorconfig": "bin/editorconfig" } }, "sha512-e0GOtq/aTQhVdNyDU9e02+wz9oDDM+SIOQxWME2QRjzRX5yyLAuHDE+0aE8vHb9XRC8XD37eO2u57+F09JqFhw=="],
"effect": ["effect@4.0.0-rc.112", "", { "dependencies": { "fast-check": "^4.9.0", "msgpackr": "^2.0.5" } }, "sha512-wXxwuh1Ywnv4cPRM3Wfa0vDwuOHnZ1TsTgHJkG9XgzND6inhBH9n1vBxhg3iIXOia/OrpmvVmd3lrD4vq6bF3A=="],
"effect": ["effect@4.0.0-rc.115", "", {}, "sha512-ogYulZ5ffeOzrJqQrG0XOkDO5lKn2s9KNHhoxJy/6wKUkF0i12dlVXWA9TgsgQ+zV/JzizyG0+XMPepZEQX6vw=="],
"ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="],
@@ -4128,7 +4118,7 @@
"github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="],
"gitlab-ai-provider": ["gitlab-ai-provider@6.16.0", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=3.0.0", "@ai-sdk/provider-utils": ">=4.0.0" } }, "sha512-HMC3sKgWYaYSsgm86Cnq2e6laHlYkhiFQ6rFD5qsVghv9//6h4Ofr7j5R2KjQx9Hl8EBercPsmzjoEjEN7dX5Q=="],
"gitlab-ai-provider": ["gitlab-ai-provider@6.12.1", "", { "dependencies": { "@anthropic-ai/sdk": "^0.71.0", "@anycable/core": "^0.9.2", "graphql-request": "^6.1.0", "isomorphic-ws": "^5.0.0", "openai": "^6.16.0", "socket.io-client": "^4.8.1", "vscode-jsonrpc": "^8.2.1", "zod": "^3.25.76" }, "peerDependencies": { "@ai-sdk/provider": ">=3.0.0", "@ai-sdk/provider-utils": ">=4.0.0" } }, "sha512-Qn5iHqvjG8yktI5MWaUgdRR94l7O4WtYW0CAbhsCh1Tj0Fei/DeprOYPVyf4Nht1Ix6U2PXSYM32QOHI6Z2TDw=="],
"glob": ["glob@13.0.5", "", { "dependencies": { "minimatch": "^10.2.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw=="],
@@ -4714,7 +4704,7 @@
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
"mime": ["mime@4.1.0", "", { "bin": { "mime": "bin/cli.js" } }, "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw=="],
"mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
@@ -4762,10 +4752,6 @@
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"msgpackr": ["msgpackr@2.0.5", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-cef05H/dSYpLpqp3sj/qyZh5vhUYCalnaLO7j1yOmpsR0y/XwLVtK7r5gn+U/F7CTEfMowcGhlUQJDLcLf7jcA=="],
"msgpackr-extract": ["msgpackr-extract@3.0.4", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw=="],
"muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="],
"mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="],
@@ -4808,8 +4794,6 @@
"node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="],
"node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="],
"node-html-parser": ["node-html-parser@7.1.0", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-iJo8b2uYGT40Y8BTyy5ufL6IVbN8rbm/1QK2xffXU/1a/v3AAa0d1YAoqBNYqaS4R/HajkWIpIfdE6KcyFh1AQ=="],
"node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
@@ -5606,7 +5590,7 @@
"uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],
"undici": ["undici@8.10.0", "", {}, "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ=="],
"undici": ["undici@8.10.2", "", {}, "sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ=="],
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
@@ -6060,8 +6044,6 @@
"@bufbuild/protoplugin/typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="],
"@cloudflare/kv-asset-handler/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
"@cloudflare/vite-plugin/vite": ["vite@7.3.6", "", { "dependencies": { "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg=="],
"@cloudflare/vite-plugin/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
@@ -6662,6 +6644,8 @@
"tw-to-css/tailwindcss": ["tailwindcss@3.3.2", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.18.2", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", "postcss": "^8.4.23", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.1", "postcss-nested": "^6.0.1", "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0", "resolve": "^1.22.2", "sucrase": "^3.32.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w=="],
"unifont/undici": ["undici@8.10.0", "", {}, "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ=="],
"unplugin/acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
"unused-filename/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
+4 -4
View File
@@ -1,8 +1,8 @@
{
"nodeModules": {
"x86_64-linux": "sha256-DVimx64BQEkFaYZkW56E5eEfkGxuW5j/9C0wCImBFl4=",
"aarch64-linux": "sha256-MhMl/ZkvcPXE31OvysutI6nKIJ6XtUa3c71+B4hnaQc=",
"aarch64-darwin": "sha256-+wMPYLBnw2zTZj0if8EPwWC9O3tVqSgnhYNfQq8UZ8Q=",
"x86_64-darwin": "sha256-l6LxVSXDbqVoXMVcGZAzRER0bxP6wDU4dfRDolx0JGM="
"x86_64-linux": "sha256-WBGj4wU5PQs+0zbDbScFhJs0GL8qWnswIsJb/Kee5Qc=",
"aarch64-linux": "sha256-Z8hkyNMdqCpuv24q50QhO2RECINvENjBhLDY5FKcnFc=",
"aarch64-darwin": "sha256-HZHb9HcXMOc7bKR7eADQSyfWxX37GAcoRi/EMSpRiP4=",
"x86_64-darwin": "sha256-CcWCOAcW4t9ADs48fMhumSbDcQWdk91LpkG6fe/gWlk="
}
}
+6 -5
View File
@@ -42,10 +42,10 @@
"packages/stats/*"
],
"catalog": {
"@effect/opentelemetry": "4.0.0-rc.112",
"@effect/platform-node": "4.0.0-rc.112",
"@effect/platform-node-shared": "4.0.0-rc.112",
"@effect/sql-sqlite-bun": "4.0.0-rc.112",
"@effect/opentelemetry": "4.0.0-rc.115",
"@effect/platform-node": "4.0.0-rc.115",
"@effect/platform-node-shared": "4.0.0-rc.115",
"@effect/sql-sqlite-bun": "4.0.0-rc.115",
"@npmcli/arborist": "9.4.0",
"@types/bun": "1.4.0",
"@types/cross-spawn": "6.0.6",
@@ -79,7 +79,8 @@
"dompurify": "3.4.14",
"drizzle-kit": "1.0.0-rc.5-ab785fc",
"drizzle-orm": "1.0.0-rc.5-169397b",
"effect": "4.0.0-rc.112",
"effect": "4.0.0-rc.115",
"fast-check": "4.9.0",
"ai": "6.0.168",
"cross-spawn": "7.0.6",
"hono": "4.10.7",
+1 -1
View File
@@ -26,7 +26,7 @@ import { OpenAI } from "@opencode/ai/providers"
* hover imports and local values to see how the public API is typed.
*/
const apiKey = Config.redacted("OPENAI_API_KEY")
const apiKey = Config.Redacted("OPENAI_API_KEY")
// 1. Configure a provider. The configured facade records provider identity,
// deployment options, authentication, and defaults. Per-modality selectors pick
+1 -1
View File
@@ -278,7 +278,7 @@ const readEnvFile = Effect.fn("RecordingEnv.readFile")(function* () {
})
const readConfigString = (provider: ConfigProvider.ConfigProvider, name: string) =>
Config.string(name)
Config.String(name)
.parse(provider)
.pipe(
Effect.match({
+29 -120
View File
@@ -1,4 +1,4 @@
import { Effect, Option, Schema } from "effect"
import { Effect, Schema } from "effect"
import { Tool } from "@opencode/schema/tool"
import { Route } from "../route/client.js"
import { Auth } from "../route/auth.js"
@@ -76,44 +76,6 @@ const OpenAIChatAssistantToolCall = Schema.Struct({
})
type OpenAIChatAssistantToolCall = Schema.Schema.Type<typeof OpenAIChatAssistantToolCall>
// `reasoning_details` carries two dialects. OpenRouter's `reasoning.*` entries
// must be replayed unmodified (`index` included), so they keep every field they
// arrived with. Kimi's OpenAI-compatible surface streams preserved thinking as
// bare `summary` / `encrypted` entries keyed by a stream-only `index`; Kimi does
// not document this publicly, so the handling follows Kimi Code (Kimi's own
// client): merge summary deltas by `index`, replay without `index`, and always
// send `reasoning_content` alongside. Anything else is dropped at the boundary.
const OpenRouterDetailFields = {
id: Schema.optional(Schema.NullOr(Schema.String)),
format: Schema.optional(Schema.String),
index: Schema.optional(Schema.Number),
signature: Schema.optional(Schema.NullOr(Schema.String)),
}
const ReasoningDetail = Schema.Union([
Schema.StructWithRest(
Schema.Struct({ type: Schema.Literal("reasoning.text"), text: Schema.optional(Schema.String), ...OpenRouterDetailFields }),
[Schema.Record(Schema.String, Schema.Unknown)],
),
Schema.StructWithRest(
Schema.Struct({
type: Schema.Literal("reasoning.summary"),
summary: Schema.optional(Schema.String),
...OpenRouterDetailFields,
}),
[Schema.Record(Schema.String, Schema.Unknown)],
),
Schema.StructWithRest(
Schema.Struct({ type: Schema.Literal("reasoning.encrypted"), data: Schema.String, ...OpenRouterDetailFields }),
[Schema.Record(Schema.String, Schema.Unknown)],
),
Schema.Struct({ type: Schema.Literal("summary"), summary: Schema.String, index: Schema.optional(Schema.Number) }),
Schema.Struct({ type: Schema.Literal("encrypted"), encrypted: Schema.String, index: Schema.optional(Schema.Number) }),
])
type ReasoningDetail = Schema.Schema.Type<typeof ReasoningDetail>
const decodeReasoningDetail = Schema.decodeUnknownOption(ReasoningDetail)
const knownReasoningDetails = (details: ReadonlyArray<unknown>) =>
details.flatMap((detail) => Option.toArray(decodeReasoningDetail(detail)))
// Intentionally omit Gemini's provider-specific `extra_content.google.thought_signature`
// extension until direct Google OpenAI-compatible routing is supported here:
// https://github.com/vercel/ai/issues/11590
@@ -303,9 +265,7 @@ export interface ParserState {
readonly finishReason?: FinishReasonDetails
readonly lifecycle: Lifecycle.State
readonly reasoningField?: string
/** A scalar reasoning field (`reasoning_content`, ...) has carried text in this stream. */
readonly reasoningTextObserved: boolean
readonly reasoningDetails: Array<ReasoningDetail>
readonly reasoningDetails: Array<unknown>
readonly reasoningDetailsObserved: boolean
readonly reasoningEmitted: boolean
readonly latestToolIndex?: number
@@ -381,21 +341,10 @@ const reasoningDetails = (parts: ReadonlyArray<ReasoningPart>, native: unknown,
return Array.isArray(details) ? details : []
})
if (parts.some((part) => Array.isArray(part.providerMetadata?.[providerMetadataKey]?.reasoningDetails)))
return knownReasoningDetails(observed).map(lowerReasoningDetail)
if (isRecord(native) && Array.isArray(native.reasoning_details))
return knownReasoningDetails(native.reasoning_details).map(lowerReasoningDetail)
return observed
if (isRecord(native) && Array.isArray(native.reasoning_details)) return native.reasoning_details
}
// Kimi rejects its stream-only `index` on requests
// ("the reasoning_details ... must not contain streaming index").
const lowerReasoningDetail = (detail: ReasoningDetail) => {
if (detail.type === "summary") return { type: detail.type, summary: detail.summary }
if (detail.type === "encrypted") return { type: detail.type, encrypted: detail.encrypted }
return detail
}
const isKimiDetail = (detail: { readonly type: string }) => detail.type === "summary" || detail.type === "encrypted"
const lowerUserMessage = Effect.fn("OpenAIChat.lowerUserMessage")(function* (
message: OpenAIChatRequestMessage,
options: LoweringOptions,
@@ -461,9 +410,6 @@ const lowerAssistantMessage = Effect.fn("OpenAIChat.lowerAssistantMessage")(func
if (observedField !== undefined) return observedField
if (nativeReasoning !== undefined) return "reasoning_content"
if (!fullyStructured || requireReasoning) return "reasoning_content"
// Kimi always expects `reasoning_content` on replayed assistant messages,
// even when thinking arrived only through structured details.
if (details?.some(isKimiDetail)) return "reasoning_content"
})()
const reasoningText = (() => {
if (configuredField !== undefined)
@@ -935,74 +881,44 @@ const reasoningDelta = (
return undefined
}
const detailText = (details: ReadonlyArray<ReasoningDetail>, hideKimiSummary: boolean) => {
const detailText = (details: ReadonlyArray<unknown>) => {
const text = details.flatMap((detail) => {
if (detail.type === "reasoning.text") return detail.text ? [detail.text] : []
if (detail.type === "reasoning.summary") return detail.summary ? [detail.summary] : []
// Kimi streams the full thinking through `reasoning_content` and a separate
// summary through details; show the summary only when nothing else does.
if (detail.type === "summary") return detail.summary && !hideKimiSummary ? [detail.summary] : []
if (!isRecord(detail)) return []
if (detail.type === "reasoning.text" && typeof detail.text === "string" && detail.text) return [detail.text]
if (detail.type === "reasoning.summary" && typeof detail.summary === "string" && detail.summary)
return [detail.summary]
return []
})
if (text.length > 0) return text.join("")
}
const appendReasoningDetails = (result: Array<ReasoningDetail>, details: ReadonlyArray<ReasoningDetail>) => {
const appendReasoningDetails = (result: Array<unknown>, details: ReadonlyArray<unknown>) => {
for (const detail of details) {
const previous = result.at(-1)
const merged = previous === undefined ? undefined : mergeReasoningDetails(previous, detail)
if (merged === undefined) {
if (
!isRecord(previous) ||
previous.type !== "reasoning.text" ||
!isRecord(detail) ||
detail.type !== "reasoning.text" ||
conflictingReasoningTextDetails(previous, detail)
) {
result.push(detail)
continue
}
result[result.length - 1] = merged
result[result.length - 1] = {
...previous,
...Object.fromEntries(Object.entries(detail).filter((entry) => entry[1] !== undefined)),
text: `${typeof previous.text === "string" ? previous.text : ""}${typeof detail.text === "string" ? detail.text : ""}`,
signature: mergeDetailValue(previous.signature, detail.signature),
format: mergeDetailValue(previous.format, detail.format),
}
}
}
// Consecutive text or summary deltas of the same kind accumulate into one
// entry; encrypted entries are opaque and never merge.
const mergeReasoningDetails = (previous: ReasoningDetail, detail: ReasoningDetail): ReasoningDetail | undefined => {
if (conflictingReasoningDetails(previous, detail)) return undefined
if (previous.type === "reasoning.text" && detail.type === "reasoning.text")
return {
...previous,
...detail,
text: `${previous.text ?? ""}${detail.text ?? ""}`,
...mergeDetailIdentity(previous, detail),
}
if (previous.type === "reasoning.summary" && detail.type === "reasoning.summary")
return {
...previous,
...detail,
summary: `${previous.summary ?? ""}${detail.summary ?? ""}`,
...mergeDetailIdentity(previous, detail),
}
if (previous.type === "summary" && detail.type === "summary")
return { ...previous, ...detail, summary: previous.summary + detail.summary }
}
type DetailIdentity = {
readonly id?: string | null
readonly index?: number
readonly format?: string
readonly signature?: string | null
}
// The first non-empty signature and format win; a later delta may carry the
// signature for text that streamed earlier.
const mergeDetailIdentity = (previous: DetailIdentity, current: DetailIdentity) => {
const signature = mergeDetailValue(previous.signature, current.signature)
const format = mergeDetailValue(previous.format, current.format)
return {
...(signature === undefined ? {} : { signature }),
...(format === undefined ? {} : { format }),
}
}
const mergeDetailValue = <T>(previous: T | undefined, current: T | undefined) =>
const mergeDetailValue = (previous: unknown, current: unknown) =>
previous || current || (previous !== undefined ? previous : current)
const conflictingReasoningDetails = (previous: DetailIdentity, current: DetailIdentity) =>
const conflictingReasoningTextDetails = (previous: Record<string, unknown>, current: Record<string, unknown>) =>
conflictingDetailValue(previous.id, current.id) ||
conflictingDetailValue(previous.index, current.index) ||
conflictingDetailValue(previous.format, current.format) ||
@@ -1014,7 +930,7 @@ const conflictingDetailValue = (previous: unknown, current: unknown) =>
const reasoningMetadata = (
providerMetadataKey: string,
field: ParserState["reasoningField"],
details?: ReadonlyArray<ReasoningDetail>,
details?: ReadonlyArray<unknown>,
) => ({
[providerMetadataKey]: {
...(field ? { reasoningField: field } : {}),
@@ -1077,16 +993,11 @@ const step = (state: ParserState, event: OpenAIChatEvent) =>
}
const reasoningField = state.reasoningField ?? reasoning?.field
const reasoningTextObserved = state.reasoningTextObserved || reasoning !== undefined
const detailDelta = Array.isArray(delta?.reasoning_details)
? knownReasoningDetails(delta.reasoning_details)
: undefined
const detailDelta = Array.isArray(delta?.reasoning_details) ? delta.reasoning_details : undefined
if (detailDelta !== undefined) appendReasoningDetails(state.reasoningDetails, detailDelta)
const reasoningDetailsObserved = state.reasoningDetailsObserved || detailDelta !== undefined
const deltaMetadata = reasoningMetadata(state.providerMetadataKey, reasoningField)
const text = detailDelta?.length
? (detailText(detailDelta, reasoningTextObserved) ?? reasoning?.text)
: reasoning?.text
const text = detailDelta?.length ? (detailText(detailDelta) ?? reasoning?.text) : reasoning?.text
if (text !== undefined) lifecycle = Lifecycle.reasoningDelta(lifecycle, events, "reasoning-0", text, deltaMetadata)
else if (
reasoningDetailsObserved &&
@@ -1182,7 +1093,6 @@ const step = (state: ParserState, event: OpenAIChatEvent) =>
finishReason,
lifecycle,
reasoningField,
reasoningTextObserved,
reasoningDetails: state.reasoningDetails,
reasoningDetailsObserved,
reasoningEmitted,
@@ -1263,7 +1173,6 @@ export const protocol = Protocol.make({
toolCallEvents: [],
lifecycle: Lifecycle.initial(),
reasoningField: request.model.compatibility?.reasoningField,
reasoningTextObserved: false,
reasoningDetails: [],
reasoningDetailsObserved: false,
reasoningEmitted: false,
+5 -9
View File
@@ -231,11 +231,11 @@ export const errorText = (error: unknown) => {
/**
* `framing` step for Server-Sent Events. Decodes UTF-8, runs the SSE channel
* decoder, optionally filters named events, and drops empty and bare `null`
* events. `[DONE]` is dropped by default or retained for protocols that use it
* as their stream boundary. Retry control events are ignored without
* interrupting the stream. Decoder failures become provider output errors so
* the public error channel stays `AIError`.
* decoder, optionally filters named events, and drops empty events. `[DONE]`
* is dropped by default or retained for protocols that use it as their stream
* boundary. Retry control events are ignored without interrupting the stream.
* Decoder failures become provider output errors so the public error channel
* stays `AIError`.
*/
export const sseFraming = (
bytes: Stream.Stream<Uint8Array, AIError>,
@@ -265,10 +265,6 @@ export const sseFraming = (
(event) =>
(events === undefined || events.has(event.event)) &&
event.data.length > 0 &&
// Some OpenAI-compatible proxies serialize an empty flush as a bare
// `data: null`, between events or after `[DONE]`. No protocol has a
// null event, so it carries nothing and must not abort the stream.
event.data !== "null" &&
(event.data !== "[DONE]" || includeDone || (events !== undefined && event.event !== "message")),
),
Stream.map((event) => event.data),
+1 -1
View File
@@ -89,7 +89,7 @@ export const optional = (secret: Secret | undefined, source = "optional value")
? credential(Effect.fail(new MissingCredentialError(source)))
: credentialFromSecret(secret, source)
export const config = (name: string) => credentialFromSecret(Config.redacted(name), name)
export const config = (name: string) => credentialFromSecret(Config.Redacted(name), name)
export const effect = (load: Effect.Effect<Redacted.Redacted, CredentialError>) => credential(load)
+28 -2
View File
@@ -6,6 +6,7 @@ import type {
ToolOutput as ToolOutputType,
} from "./schema/index.js"
import { ToolDefinition, ToolFailure, ToolOutput } from "./schema/index.js"
import { isRecord } from "./utils/record.js"
/**
* Schema constraint for tool parameters / success values: no decoding or
@@ -200,7 +201,7 @@ export function make(config: TypedToolConfig | DynamicToolConfig): AnyTool {
_definition: new ToolDefinition({
name: "",
description: config.description,
inputSchema: toJsonSchema(config.parameters),
inputSchema: toInputJsonSchema(config.parameters),
outputSchema: toJsonSchema(config.success),
}),
}
@@ -230,8 +231,33 @@ export const toDefinitions = (tools: Tools): ReadonlyArray<ToolDefinitionClass>
}),
)
const toInputJsonSchema = (schema: Schema.Top): JsonSchema.JsonSchema => {
// Effect represents Struct({}) as any non-null value; tool parameters must
// instead describe an object. Inline named empty inputs so providers such as
// Gemini can recognize a no-argument tool, while retaining schema annotations.
if (
schema.ast._tag !== "Objects" ||
schema.ast.propertySignatures.length !== 0 ||
schema.ast.indexSignatures.length !== 0 ||
schema.ast.encoding !== undefined ||
schema.ast.checks !== undefined
)
return toJsonSchema(schema)
const json = Schema.toJsonSchemaDocument(schema, {
onExcessProperty: "error",
referencePolicy: () => undefined,
}).schema
if (isRecord(json.not) && json.not.type === "null" && Object.keys(json.not).length === 1) {
const normalized: JsonSchema.JsonSchema = { type: "object", properties: {}, additionalProperties: false, ...json }
delete normalized.not
return normalized
}
return toJsonSchema(schema)
}
const toJsonSchema = (schema: Schema.Top): JsonSchema.JsonSchema => {
const document = Schema.toJsonSchemaDocument(schema)
const document = Schema.toJsonSchemaDocument(schema, { onExcessProperty: "error" })
if (Object.keys(document.definitions).length === 0) return document.schema
return { ...document.schema, $defs: document.definitions }
}
+1 -1
View File
@@ -30,7 +30,7 @@ type LanguageModel = {
declare const auth: Auth.Definition
declare const optionalAuthModel: LanguageModelFactory<BaseOptions, "optional", LanguageModel>
declare const requiredAuthModel: LanguageModelFactory<BaseOptions, "required", LanguageModel>
const configApiKey = Config.redacted("OPENAI_API_KEY")
const configApiKey = Config.Redacted("OPENAI_API_KEY")
OpenAIChat.route.model({ id: "gpt-4.1-mini" })
+3 -184
View File
@@ -1182,9 +1182,7 @@ describe("OpenAI Chat route", () => {
}),
)
// Only recognized detail shapes are retained and replayed; echoing an
// undocumented provider payload is what breaks follow-up requests.
it.effect("drops unknown reasoning details while using scalar display text", () =>
it.effect("preserves unknown reasoning details while using scalar display text", () =>
Effect.gen(function* () {
const details = [{ type: "reasoning.future", format: "provider-v2", state: { opaque: true } }]
const response = yield* LLMClient.generate(request).pipe(
@@ -1201,195 +1199,16 @@ describe("OpenAI Chat route", () => {
expect(response.reasoning).toBe("thinking")
expect(response.message.content.find((part) => part.type === "reasoning")?.providerMetadata).toEqual({
openai: { reasoningField: "reasoning", reasoningDetails: [] },
openai: { reasoningField: "reasoning", reasoningDetails: details },
})
const replay = yield* compileRequest(LLM.request({ model, messages: [response.message] }))
expect(replay.body.messages).toEqual([
{ role: "assistant", content: "Hello", reasoning: "thinking", reasoning_details: [] },
{ role: "assistant", content: "Hello", reasoning: "thinking", reasoning_details: details },
])
}),
)
// Kimi's coding endpoint streams the full thinking through `reasoning_content`
// and a separate summary + encrypted blob through its own `reasoning_details`
// dialect. The stream-only `index` must not be echoed back.
it.effect("merges Kimi summary deltas by index and replays details without the streaming index", () =>
Effect.gen(function* () {
const response = yield* LLMClient.generate(request).pipe(
Effect.provide(
fixedResponse(
sseEvents(
{ choices: [{ delta: { reasoning_content: "Let me" } }] },
{ choices: [{ delta: { reasoning_content: " think" } }] },
{ choices: [{ delta: { reasoning_details: [{ index: 0, type: "summary", summary: "Plan" }] } }] },
{ choices: [{ delta: { reasoning_details: [{ index: 0, type: "summary", summary: " tools" }] } }] },
{ choices: [{ delta: { reasoning_details: [{ index: 1, type: "encrypted", encrypted: "opaque" }] } }] },
{
choices: [
{
delta: {
tool_calls: [
{ index: 0, id: "call_1", type: "function", function: { name: "get_time", arguments: "{}" } },
],
},
},
],
},
{ choices: [{ delta: {}, finish_reason: "tool_calls" }] },
),
),
),
)
const stored = [
{ index: 0, type: "summary", summary: "Plan tools" },
{ index: 1, type: "encrypted", encrypted: "opaque" },
]
expect(response.reasoning).toBe("Let me think")
expect(response.message.content.find((part) => part.type === "reasoning")?.providerMetadata).toEqual({
openai: { reasoningField: "reasoning_content", reasoningDetails: stored },
})
const replay = yield* compileRequest(LLM.request({ model, messages: [response.message] }))
expect(replay.body.messages).toEqual([
{
role: "assistant",
content: null,
tool_calls: [{ id: "call_1", type: "function", function: { name: "get_time", arguments: "{}" } }],
reasoning_content: "Let me think",
reasoning_details: [
{ type: "summary", summary: "Plan tools" },
{ type: "encrypted", encrypted: "opaque" },
],
},
])
}),
)
it.effect("displays Kimi summaries and replays reasoning_content when no scalar reasoning streams", () =>
Effect.gen(function* () {
const response = yield* LLMClient.generate(request).pipe(
Effect.provide(
fixedResponse(
sseEvents(
{ choices: [{ delta: { reasoning_details: [{ index: 0, type: "summary", summary: "Plan" }] } }] },
{ choices: [{ delta: { reasoning_details: [{ index: 0, type: "summary", summary: " tools" }] } }] },
{ choices: [{ delta: { reasoning_details: [{ index: 1, type: "encrypted", encrypted: "opaque" }] } }] },
{ choices: [{ delta: { content: "Hello" } }] },
{ choices: [{ delta: {}, finish_reason: "stop" }] },
),
),
),
)
expect(response.reasoning).toBe("Plan tools")
const replay = yield* compileRequest(LLM.request({ model, messages: [response.message] }))
expect(replay.body.messages).toEqual([
{
role: "assistant",
content: "Hello",
reasoning_content: "Plan tools",
reasoning_details: [
{ type: "summary", summary: "Plan tools" },
{ type: "encrypted", encrypted: "opaque" },
],
},
])
}),
)
// Sessions persisted before the fix already hold Kimi details with `index`.
it.effect("strips the streaming index from previously stored Kimi details", () =>
Effect.gen(function* () {
const replay = yield* compileRequest(
LLM.request({
model,
messages: [
Message.assistant([
{
type: "reasoning",
text: "thinking",
providerMetadata: {
openai: {
reasoningField: "reasoning_content",
reasoningDetails: [
{ index: 0, type: "summary", summary: "thinking" },
{ index: 1, type: "encrypted", encrypted: "opaque" },
],
},
},
},
]),
],
}),
)
expect(replay.body.messages).toEqual([
{
role: "assistant",
content: "",
reasoning_content: "thinking",
reasoning_details: [
{ type: "summary", summary: "thinking" },
{ type: "encrypted", encrypted: "opaque" },
],
},
])
}),
)
it.effect("merges consecutive OpenRouter summary deltas and replays them unmodified", () =>
Effect.gen(function* () {
const merged = [
{ type: "reasoning.summary", summary: "Plan tools", format: "openai-responses-v1", index: 0 },
{ type: "reasoning.encrypted", data: "opaque", format: "openai-responses-v1", index: 0 },
]
const response = yield* LLMClient.generate(request).pipe(
Effect.provide(
fixedResponse(
sseEvents(
{
choices: [
{
delta: {
reasoning_details: [
{ type: "reasoning.summary", summary: "Plan", format: "openai-responses-v1", index: 0 },
],
},
},
],
},
{
choices: [
{
delta: {
reasoning_details: [
{ type: "reasoning.summary", summary: " tools", format: "openai-responses-v1", index: 0 },
],
},
},
],
},
{ choices: [{ delta: { reasoning_details: [merged[1]] } }] },
{ choices: [{ delta: { content: "Hello" } }] },
{ choices: [{ delta: {}, finish_reason: "stop" }] },
),
),
),
)
expect(response.reasoning).toBe("Plan tools")
expect(response.message.content.find((part) => part.type === "reasoning")?.providerMetadata).toEqual({
openai: { reasoningDetails: merged },
})
const replay = yield* compileRequest(LLM.request({ model, messages: [response.message] }))
expect(replay.body.messages).toEqual([{ role: "assistant", content: "Hello", reasoning_details: merged }])
}),
)
it.effect("uses scalar display text for signature-only reasoning details", () =>
Effect.gen(function* () {
const details = [{ type: "reasoning.text", signature: "signed", format: "provider-v2", index: 0 }]
@@ -375,27 +375,6 @@ describe("OpenAI-compatible Chat route", () => {
}),
)
it.effect("ignores bare null frames between deltas", () =>
Effect.gen(function* () {
const response = yield* LLMClient.generate(request).pipe(
Effect.provide(
fixedResponse(
sseEvents(
deltaChunk({ role: "assistant", content: "Hello" }),
"null",
deltaChunk({ content: "!" }),
"null",
deltaChunk({}, "stop"),
),
),
),
)
expect(response.text).toBe("Hello!")
expect(response.finishReason).toEqual({ normalized: "stop", raw: "stop" })
}),
)
it.effect("accepts nullable usage and preserves provider fields", () =>
Effect.gen(function* () {
const response = yield* LLMClient.generate(request).pipe(
@@ -393,33 +393,6 @@ describe("Open Responses-compatible route", () => {
}),
)
it.effect("ignores bare null frames between events", () =>
Effect.gen(function* () {
const model = configure({
apiKey: "test-key",
baseURL: "https://responses.example.test/v1",
}).model("example-model")
const response = yield* LLMClient.generate(LLM.request({ model, prompt: "Say hello." })).pipe(
Effect.provide(
fixedResponse(
sseEvents(
{ type: "response.output_item.added", output_index: 0, item: { type: "message", id: "msg_1" } },
"null",
{ type: "response.output_text.delta", output_index: 0, item_id: "msg_1", delta: "Hello" },
"null",
{ type: "response.output_item.done", output_index: 0, item: { type: "message", id: "msg_1" } },
{ type: "response.completed", response: { id: "resp_1" } },
"null",
),
),
),
)
expect(response.text).toBe("Hello")
expect(response.events.at(-1)).toMatchObject({ type: "finish" })
}),
)
describe("stream validation", () => {
const request = LLM.request({
model: configure({ apiKey: "test-key", baseURL: "https://responses.example.test/v1" }).model("example-model"),
+3 -10
View File
@@ -315,9 +315,10 @@ describe("OpenRouter", () => {
}),
)
it.effect("drops unrecognized details and preserves duplicate continuation details", () =>
it.effect("preserves opaque and duplicate continuation details", () =>
Effect.gen(function* () {
const details = [
{ type: "reasoning.future", format: "provider-v2", state: { opaque: true } },
{ type: "reasoning.encrypted", id: "state", data: "opaque" },
{ type: "reasoning.encrypted", id: "state", data: "opaque" },
]
@@ -329,15 +330,7 @@ describe("OpenRouter", () => {
Message.assistant({
type: "reasoning",
text: "Thinking",
providerMetadata: {
openrouter: {
reasoningField: "reasoning",
reasoningDetails: [
{ type: "reasoning.future", format: "provider-v2", state: { opaque: true } },
...details,
],
},
},
providerMetadata: { openrouter: { reasoningField: "reasoning", reasoningDetails: details } },
}),
],
}),
-14
View File
@@ -178,20 +178,6 @@ describe("AI.Usage", () => {
}),
)
it.effect("sseFraming drops bare null frames and keeps other payloads", () =>
Effect.gen(function* () {
const frames = yield* ProviderShared.sseFraming(
Stream.make(
new TextEncoder().encode(
'data: {"first":true}\n\ndata: null\n\nevent: update\ndata: null\n\ndata: "null"\n\ndata: 0\n\ndata: {"second":true}\n\ndata: [DONE]\n\ndata: null\n\n',
),
),
).pipe(Stream.runCollect)
expect(Array.from(frames)).toEqual(['{"first":true}', '"null"', "0", '{"second":true}'])
}),
)
test("visibleOutputTokens clamps reasoning > output to zero", () => {
expect(new Usage({ outputTokens: 10, reasoningTokens: 4 }).visibleOutputTokens).toBe(6)
expect(new Usage({ outputTokens: 10 }).visibleOutputTokens).toBe(10)
+135 -3
View File
@@ -1,13 +1,145 @@
import { describe, expect, test } from "bun:test"
import { Effect } from "effect"
import { LLM } from "../src/index.js"
import { OpenAIChat } from "../src/protocols.js"
import { Effect, Schema } from "effect"
import { LLM, Tool } from "../src/index.js"
import { AnthropicMessages, Gemini, OpenAIChat, OpenAIResponses } from "../src/protocols.js"
import { ToolSchemaProjection } from "../src/protocols/utils/tool-schema.js"
import { Auth } from "../src/route.js"
import { compileRequest } from "../src/route/client.js"
import { it } from "./lib/effect.js"
describe("tool schema projections", () => {
test("only normalizes typed empty input structs, preserving raw schemas and output schemas", () => {
const schema = { not: { type: "null" } }
const definitions = Tool.toDefinitions({
typed: Tool.make({
description: "Typed",
parameters: Schema.Struct({}),
success: Schema.Struct({}),
execute: () => Effect.succeed({}),
}),
raw: Tool.make({ description: "Raw", jsonSchema: schema, execute: () => Effect.succeed({}) }),
})
expect(definitions[0]?.inputSchema).toEqual({ type: "object", properties: {}, additionalProperties: false })
expect(definitions[0]?.outputSchema).toEqual(schema)
expect(definitions[1]?.inputSchema).toEqual(schema)
})
test("retains empty input descriptions and preserves named outputs and explicit raw schemas", () => {
const parameters = Schema.Struct({}).annotate({ identifier: "Ping", description: "No arguments" })
const raw = { $ref: "#/$defs/Raw", $defs: { Raw: { not: { type: "null" }, description: "Raw schema" } } }
const definitions = Tool.toDefinitions({
typed: Tool.make({ description: "Ping", parameters, success: parameters, execute: () => Effect.succeed({}) }),
raw: Tool.make({ description: "Raw", jsonSchema: raw, execute: () => Effect.succeed({}) }),
})
expect(definitions[0]?.inputSchema).toEqual({
type: "object",
properties: {},
additionalProperties: false,
description: "No arguments",
})
expect(definitions[0]?.outputSchema).toEqual({
$ref: "#/$defs/Ping",
$defs: { Ping: { not: { type: "null" }, description: "No arguments" } },
})
expect(definitions[1]?.inputSchema).toEqual(raw)
})
const empty = { type: "object", properties: {}, additionalProperties: false }
const nonempty = {
type: "object",
properties: { query: { type: "string" } },
required: ["query"],
additionalProperties: false,
}
const raw = { type: "object", properties: { value: { type: "number" } }, additionalProperties: true }
for (const scenario of [
{
route: OpenAIChat.route,
tools: [empty, nonempty, raw].map((parameters, index) => ({
type: "function",
function: { name: ["ping", "lookup", "raw"][index], parameters },
})),
},
{
route: OpenAIResponses.route,
tools: [empty, nonempty, raw].map((parameters, index) => ({
type: "function",
name: ["ping", "lookup", "raw"][index],
parameters,
})),
},
{
route: AnthropicMessages.route,
tools: [empty, nonempty, raw].map((input_schema, index) => ({
name: ["ping", "lookup", "raw"][index],
input_schema,
})),
},
{
route: Gemini.route,
tools: [
{
functionDeclarations: [
{ name: "ping", description: "Ping" },
{
name: "lookup",
description: "Lookup",
parameters: {
type: "object",
properties: nonempty.properties,
required: nonempty.required,
},
},
{ name: "raw", description: "Raw", parameters: { type: "object", properties: raw.properties } },
],
},
],
},
]) {
for (const input of [
{ name: "plain", schema: Schema.Struct({}) },
{ name: "described", schema: Schema.Struct({}).annotate({ description: "No arguments" }) },
{ name: "named", schema: Schema.Struct({}).annotate({ identifier: "Ping" }) },
{
name: "named and described",
schema: Schema.Struct({}).annotate({ identifier: "Ping", description: "No arguments" }),
},
]) {
it.effect(
`${scenario.route.id} prepares ${input.name} empty Effect Struct tools alongside nonempty and raw schemas`,
() =>
Effect.gen(function* () {
const prepared = yield* compileRequest(
LLM.request({
model: scenario.route.with({ auth: Auth.bearer("test") }).model({ id: "test-model" }),
prompt: "Use a tool.",
tools: Tool.toDefinitions({
ping: Tool.make({
description: "Ping",
parameters: input.schema,
success: Schema.String,
execute: () => Effect.succeed("pong"),
}),
lookup: Tool.make({
description: "Lookup",
parameters: Schema.Struct({ query: Schema.String }),
success: Schema.String,
execute: (input) => Effect.succeed(input.query),
}),
raw: Tool.make({ description: "Raw", jsonSchema: raw, execute: () => Effect.succeed("raw") }),
}),
}),
)
expect(prepared.body.tools).toMatchObject(scenario.tools)
if (scenario.route.id === "gemini") {
expect(prepared.body.tools).toEqual(scenario.tools)
}
}),
)
}
}
test("moonshot strips $ref siblings and converts tuple arrays to a schema object", () => {
expect(
ToolSchemaProjection.moonshot({
@@ -1,94 +0,0 @@
import { expect, test, type Page } from "@playwright/test"
import { mockOpenCodeServer } from "../utils/mock-server"
const directory = "C:/Projects/providers-console-signin"
const project = {
id: "proj_providers_console",
canonical: directory,
name: "Providers console",
vcs: "git",
time: { created: 1700000000000, updated: 1700000000000 },
sandboxes: [],
}
// Zen and the Console account share the id `opencode`: the provider comes from models.dev, the
// integration is renamed by OpencodePlugin and carries the account sign-in.
const zen = (paid: boolean) => ({
id: "opencode",
name: "OpenCode Zen",
models: {
"claude-sonnet-4-6": {
id: "claude-sonnet-4-6",
name: "Claude Sonnet 4.6",
cost: { input: paid ? 3 : 0, output: 0 },
},
},
})
const integrations = (connections: unknown[]) => [
{
id: "opencode",
name: "OpenCode Console",
methods: [
{ id: "device", type: "oauth", label: "OpenCode Console account" },
{ type: "key", label: "API key (service account)" },
],
connections,
},
{ id: "opencode-go", name: "OpenCode Go", methods: [{ type: "key" }], connections: [] },
{ id: "anthropic", name: "Anthropic", methods: [{ type: "key" }], connections: [] },
]
test.use({ viewport: { width: 1280, height: 900 } })
async function openProviders(page: Page, input: { paid: boolean; connections: unknown[] }) {
await mockOpenCodeServer(page, {
directory,
project,
provider: { all: [zen(input.paid)], connected: ["opencode"], default: {} },
integrations: integrations(input.connections),
sessions: [],
pageMessages: () => ({ items: [] }),
})
await page.addInitScript((directory) => {
localStorage.setItem(
"opencode.global.dat:server",
JSON.stringify({ projects: { local: [{ worktree: directory, expanded: true }] } }),
)
}, directory)
await page.goto("/")
await page.getByRole("button", { name: "Settings", exact: true }).click()
const settings = page.getByTestId("settings-screen")
await settings.getByRole("tab", { name: "Providers", exact: true }).click()
await expect(settings.getByRole("heading", { name: "Popular providers" })).toBeVisible()
return settings
}
test("fresh install offers the Console sign-in", async ({ page }) => {
const settings = await openProviders(page, { paid: false, connections: [] })
await expect(settings.getByText("No connected providers")).toBeVisible()
await expect(settings.getByText("OpenCode Console", { exact: true })).toBeVisible()
})
test("a stored Zen API key keeps the Console sign-in available", async ({ page }) => {
const settings = await openProviders(page, {
paid: true,
connections: [{ type: "credential", id: "cred_v1", label: "API key", method: "key" }],
})
const connected = settings.locator('[data-component="connected-providers-section"]')
await expect(connected.getByText("OpenCode Zen", { exact: true })).toBeVisible()
await expect(settings.getByText("OpenCode Console", { exact: true })).toBeVisible()
})
test("a Console account hides the sign-in row", async ({ page }) => {
const settings = await openProviders(page, {
paid: true,
connections: [{ type: "credential", id: "cred_account", label: "Clara Team", method: "oauth" }],
})
const connected = settings.locator('[data-component="connected-providers-section"]')
await expect(connected.getByText("OpenCode Zen", { exact: true })).toBeVisible()
// Anthropic only exists in the integration fixture, so its row proves the integration list has loaded.
await expect(settings.getByText("Anthropic", { exact: true })).toBeVisible()
await expect(settings.getByText("OpenCode Console", { exact: true })).toHaveCount(0)
})
+2 -5
View File
@@ -9,7 +9,6 @@ export interface MockServerConfig {
server?: string
provider: unknown | (() => unknown)
integrationMethods?: Record<string, unknown[]>
integrations?: unknown[]
onConnectKey?: (input: { integrationID: string; body: unknown }) => void
shells?: unknown[]
configEntries?: unknown[]
@@ -259,13 +258,11 @@ function mockHandlers(config: MockServerConfig, state: { cursors: Map<string, st
model: () => Effect.succeed({ location: location(config), data: currentModels(providerConfig(config)) }),
modelDefault: () =>
Effect.succeed({ location: location(config), data: currentDefaultModel(providerConfig(config)) }),
integrationList: () => Effect.succeed({ location: location(config), data: config.integrations ?? [] }),
integrationList: () => Effect.succeed({ location: location(config), data: [] }),
integrationGet: (ctx) =>
Effect.succeed({
location: location(config),
data: config.integrations
?.filter(record)
.find((integration) => integration.id === ctx.params.integrationID) ?? {
data: {
id: ctx.params.integrationID,
name: ctx.params.integrationID,
methods: config.integrationMethods?.[ctx.params.integrationID] ?? [{ type: "key", label: "API key" }],
@@ -45,7 +45,7 @@ const Current = Persistence.struct({ session: SessionsSchema })
export const ModelSelectionSchema = Persistence.migrate(
Current,
Schema.Struct({
Persistence.legacy({
session: Persistence.optional(Schema.Record(Schema.String, Schema.Unknown)),
pick: Persistence.optional(Schema.Record(Schema.String, Schema.Unknown)),
}).pipe(
@@ -32,7 +32,7 @@ describe("persistence schemas", () => {
test("legacy migration observes missing fields before initial defaults are applied", () => {
const current = Persistence.struct({ mode: Schema.Literals(["compact", "full"]), enabled: Schema.Boolean })
const stored = Schema.Struct({
const stored = Persistence.legacy({
mode: Schema.optional(Schema.Unknown),
expanded: Schema.optional(Schema.Boolean),
}).pipe(
@@ -53,6 +53,38 @@ describe("persistence schemas", () => {
expect(Schema.encodeSync(schema)(decode({ expanded: true }))).toEqual({ mode: "full", enabled: true })
})
test("legacy read shapes carry unknown nested fields through to the current schema", () => {
const current = Persistence.struct({
general: Persistence.struct({
mode: Schema.Literals(["compact", "full"]),
theme: Schema.String,
nested: Persistence.struct({ keep: Schema.Boolean }),
}),
other: Persistence.struct({ flag: Schema.Boolean }),
})
const stored = Persistence.legacy({
general: Persistence.optional(Persistence.legacy({ expanded: Persistence.optional(Schema.Boolean) })),
}).pipe(
Schema.decode({
decode: SchemaGetter.transform((value) => {
const general = value.general
if (!general || general.expanded === undefined) return value
return { ...value, general: { ...general, mode: general.expanded ? "full" : "compact" } }
}),
encode: SchemaGetter.passthrough(),
}),
)
const schema = Persistence.withInitial(Persistence.migrate(current, stored), {
general: { mode: "compact", theme: "light", nested: { keep: false } },
other: { flag: false },
})
const decode = Schema.decodeUnknownSync(schema)
expect(decode({ general: { expanded: true, theme: "dark", nested: { keep: true } }, other: { flag: true } })).toEqual({
general: { mode: "full", theme: "dark", nested: { keep: true } },
other: { flag: true },
})
})
test("initial merging preserves field codecs and replaces arrays rather than merging indexes", () => {
const current = Persistence.struct({
amount: Schema.NumberFromString.check(Schema.isFinite()),
@@ -23,13 +23,11 @@ export function withInitial<S extends Schema.ConstraintCodec<object, unknown>>(
initial: NoInfer<S["Type"]>,
) {
const schema = isMigrated(definition) ? definition.current : definition
const read = isMigrated(definition)
? SchemaParser.decodeUnknownResult(definition.read, { onExcessProperty: "preserve" })
: Result.succeed<unknown>
const read = isMigrated(definition) ? SchemaParser.decodeUnknownResult(definition.read) : Result.succeed<unknown>
const encode = Schema.encodeUnknownSync(schema)
return Schema.Unknown.pipe(
Schema.decode<Schema.Unknown>({
decode: SchemaGetter.transformOrFail((value) =>
decode: SchemaGetter.transformEffect((value) =>
Effect.fromResult(Result.map(read(value), (stored) => merge(initial, recover(schema.ast, stored, initial)))),
),
encode: SchemaGetter.transform((value) => encode(value)),
@@ -38,6 +36,12 @@ export function withInitial<S extends Schema.ConstraintCodec<object, unknown>>(
)
}
// A legacy read shape declares only the fields it migrates. Decoding strips unknown keys, so every
// struct level in a `migrate` read schema must stay open for the current fields it does not name.
export function legacy<const Fields extends Schema.Struct.Fields>(fields: Fields) {
return Schema.StructWithRest(Schema.Struct(fields), [Schema.Record(Schema.String, Schema.Unknown)])
}
// Object-level codecs own their recovery. Plain structs can recover fields independently.
function recover(ast: SchemaAST.AST, value: unknown, initial: unknown): unknown {
if (value === undefined) return initial
@@ -93,7 +93,7 @@ describe("normalizeProviderList", () => {
describe("normalizeProjectInfo", () => {
test("keeps the project VCS backend", () => {
const project = { id: "prj", canonical: "/repo", time: { created: 1, updated: 1, active: 1 }, sandboxes: [] }
const project = { id: "prj", canonical: "/repo", time: { created: 1, updated: 1 }, sandboxes: [] }
expect(normalizeProjectInfo({ ...project, vcs: "git" } as Project).vcs).toBe("git")
expect(normalizeProjectInfo({ ...project, vcs: "hg" } as Project).vcs).toBe("hg")
expect(normalizeProjectInfo(project as Project).vcs).toBeUndefined()
@@ -124,7 +124,7 @@ describe("updateProjectInfo", () => {
canonical: "/repo",
name: "Repo",
icon: { color: "purple" },
time: { created: 1, updated: 2, active: 2 },
time: { created: 1, updated: 2 },
sandboxes: ["/repo-sandbox"],
} satisfies Project
@@ -99,13 +99,13 @@ describe("readLocalImage", () => {
test.each([400, 401])("propagates declared API errors (%s)", async (status) => {
const error = { _tag: "RequestError", message: "Cannot read image" }
const { api } = setup(() => Response.json(error, { status }))
await expect(readLocalImage(api, "/repo", "image.png", new AbortController().signal)).rejects.toMatchObject(error)
await expect(readLocalImage(api, "/repo", "image.png", new AbortController().signal)).rejects.toEqual(error)
})
test("propagates missing-file errors", async () => {
const error = { _tag: "FileNotFoundError", path: "image.png", message: "File not found: image.png" }
const { api } = setup(() => Response.json(error, { status: 404 }))
await expect(readLocalImage(api, "/repo", "image.png", new AbortController().signal)).rejects.toMatchObject(error)
await expect(readLocalImage(api, "/repo", "image.png", new AbortController().signal)).rejects.toEqual(error)
})
test("does not turn an unexpected HTTP status into a Blob", async () => {
@@ -53,7 +53,7 @@ const State = Persistence.struct({
export function serverState(canonicalLocalServer: () => string | undefined = () => undefined) {
return Persistence.migrate(
State,
Schema.Struct({ projects: Projects, lastProject: LastProject }).pipe(
Persistence.legacy({ projects: Projects, lastProject: LastProject }).pipe(
Schema.decode({
decode: SchemaGetter.transform((value) => {
const canonical = canonicalLocalServer()
+2 -2
View File
@@ -188,9 +188,9 @@ function legacyTimelineActivity(value: boolean | "hidden" | "compact" | "full" |
export const settingsPersistence = Persistence.migrate(
settingsSchema,
Schema.Struct({
Persistence.legacy({
general: Persistence.optional(
Schema.Struct({
Persistence.legacy({
// Keep invalid explicit values distinct from absent values so legacy preferences cannot replace them.
timelineDetail: Schema.optional(
Schema.NullOr(
@@ -8,7 +8,6 @@ import { useIntegrations } from "@/providers/catalog/integrations"
import { createMemo, type Component, For, Show } from "solid-js"
import { useLanguage } from "@/runtime/i18n/language"
import { useServerSDK } from "@/runtime/server/client"
import { CONSOLE_INTEGRATION } from "@/providers/connect/controller"
import { DialogConnectProvider, useProviderConnectController } from "@/providers/connect/dialog"
import { SettingsList } from "@/settings/list"
import "@/settings/settings.css"
@@ -63,17 +62,9 @@ export const SettingsProviders: Component<{
const popular = createMemo(() => {
const connectedIDs = new Set(connected().map((p) => p.id))
// The Console account (integration `opencode`) shares its id with the Zen provider. A stored API
// key, including one imported from a v1 auth.json, makes Zen "connected" without any account, so
// the Popular list keeps the sign-in row until the active credential is an OAuth grant. Until the
// integration list arrives the row is still the models.dev Zen provider, so dedupe it as before.
const console = integrations.list().find((entry) => entry.id === CONSOLE_INTEGRATION)
const items = providers
.popular()
.filter((p) => {
if (p.id !== CONSOLE_INTEGRATION || !console) return !connectedIDs.has(p.id)
return console.connections.find((connection) => connection.type === "credential")?.method !== "oauth"
})
.filter((p) => !connectedIDs.has(p.id))
.slice()
items.sort((a, b) => popularProviders.indexOf(a.id) - popularProviders.indexOf(b.id))
return items
@@ -24,7 +24,7 @@ test("settings project inventory reads metadata without acquiring directory stor
name: `Project ${index}`,
icon: { color: "orange" },
commands: { start: "bun install" },
time: { created: 1, updated: 1, active: 1 },
time: { created: 1, updated: 1 },
sandboxes: [],
worktrees: [],
}))
+4 -4
View File
@@ -176,16 +176,16 @@ export const layoutSchema = Persistence.struct({
export const layoutPersistence = Persistence.migrate(
layoutSchema,
Schema.Struct({
Persistence.legacy({
sidebar: Persistence.optional(
Schema.Struct({
Persistence.legacy({
workspaces: Persistence.optional(Schema.Union([Schema.Boolean, Schema.Record(Schema.String, Schema.Boolean)])),
workspacesDefault: Persistence.optional(Schema.Boolean),
}),
),
review: Persistence.optional(Schema.Struct({ panelOpened: Persistence.optional(Schema.Boolean) })),
review: Persistence.optional(Persistence.legacy({ panelOpened: Persistence.optional(Schema.Boolean) })),
fileTree: Persistence.optional(
Schema.Struct({
Persistence.legacy({
opened: Persistence.optional(Schema.Boolean),
width: Persistence.optional(Schema.Finite),
tab: Persistence.optional(Schema.Literals(["changes", "all"])),
@@ -107,7 +107,7 @@ describe("withWorktreeInventory", () => {
id: "project",
canonical: "/repo",
name: "Before",
time: { created: 1, updated: 1, active: 1 },
time: { created: 1, updated: 1 },
sandboxes: [],
}
+95 -93
View File
@@ -3,8 +3,8 @@ import { Schema } from "effect"
import { Spec } from "../framework/spec"
import { Updater } from "../services/updater"
export const PrintLogs = GlobalFlag.setting("print-logs")({
flag: Flag.boolean("print-logs").pipe(
export const PrintLogs = GlobalFlag.Setting("print-logs")({
flag: Flag.Boolean("print-logs").pipe(
Flag.withDescription("Print logs to stderr (server logs require --standalone)"),
Flag.withDefault(false),
),
@@ -13,23 +13,23 @@ export const PrintLogs = GlobalFlag.setting("print-logs")({
declare const OPENCODE_CLI_NAME: string | undefined
const ServerParams = {
standalone: Flag.boolean("standalone").pipe(
standalone: Flag.Boolean("standalone").pipe(
Flag.withDescription("Run with a private server instead of the background service"),
Flag.withDefault(false),
),
server: Flag.string("server").pipe(
server: Flag.String("server").pipe(
Flag.withDescription("Connect to a server URL instead of the background service"),
Flag.optional,
),
}
const PermissionParams = {
auto: Flag.boolean("auto").pipe(
auto: Flag.Boolean("auto").pipe(
Flag.withDescription("Auto-approve permissions that are not explicitly denied"),
Flag.withDefault(false),
),
yolo: Flag.boolean("yolo").pipe(Flag.withDefault(false), Flag.withHidden),
dangerouslySkipPermissions: Flag.boolean("dangerously-skip-permissions").pipe(
yolo: Flag.Boolean("yolo").pipe(Flag.withDefault(false), Flag.withHidden),
dangerouslySkipPermissions: Flag.Boolean("dangerously-skip-permissions").pipe(
Flag.withDefault(false),
Flag.withHidden,
),
@@ -40,32 +40,32 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
params: {
...ServerParams,
...PermissionParams,
directory: Argument.string("directory").pipe(
directory: Argument.String("directory").pipe(
Argument.withDescription("Directory to start OpenCode in"),
Argument.optional,
),
continue: Flag.boolean("continue").pipe(
continue: Flag.Boolean("continue").pipe(
Flag.withAlias("c"),
Flag.withDescription("Continue the last session"),
Flag.withDefault(false),
),
session: Flag.string("session").pipe(
session: Flag.String("session").pipe(
Flag.withAlias("s"),
Flag.withDescription("Session ID to continue"),
Flag.optional,
),
prompt: Flag.string("prompt").pipe(Flag.withDescription("Prompt to use"), Flag.optional),
prompt: Flag.String("prompt").pipe(Flag.withDescription("Prompt to use"), Flag.optional),
},
commands: [
Spec.make("upgrade", {
description: "Upgrade OpenCode to the latest or a specific version",
aliases: ["update"],
params: {
target: Argument.string("target").pipe(
target: Argument.String("target").pipe(
Argument.withDescription("Version to upgrade to (with or without a leading v)"),
Argument.optional,
),
method: Flag.choice("method", Updater.methods).pipe(
method: Flag.Literals("method", Updater.methods).pipe(
Flag.withAlias("m"),
Flag.withDescription("Installation method to use"),
Flag.optional,
@@ -75,21 +75,21 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("uninstall", {
description: "Uninstall OpenCode and remove all related files",
params: {
keepConfig: Flag.boolean("keep-config").pipe(
keepConfig: Flag.Boolean("keep-config").pipe(
Flag.withAlias("c"),
Flag.withDescription("Keep configuration files"),
Flag.withDefault(false),
),
keepData: Flag.boolean("keep-data").pipe(
keepData: Flag.Boolean("keep-data").pipe(
Flag.withAlias("d"),
Flag.withDescription("Keep session data and snapshots"),
Flag.withDefault(false),
),
dryRun: Flag.boolean("dry-run").pipe(
dryRun: Flag.Boolean("dry-run").pipe(
Flag.withDescription("Show what would be removed without removing"),
Flag.withDefault(false),
),
force: Flag.boolean("force").pipe(
force: Flag.Boolean("force").pipe(
Flag.withAlias("f"),
Flag.withDescription("Skip confirmation prompts"),
Flag.withDefault(false),
@@ -101,17 +101,17 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
description: "Make a request to the running server",
params: {
...ServerParams,
request: Argument.string("operation | method path").pipe(
request: Argument.String("operation | method path").pipe(
Argument.withDescription("OpenAPI operation ID, or an HTTP method followed by a path"),
Argument.variadic({ min: 1, max: 2 }),
),
data: Flag.string("data").pipe(Flag.withAlias("d"), Flag.withDescription("Request body"), Flag.optional),
header: Flag.string("header").pipe(
data: Flag.String("data").pipe(Flag.withAlias("d"), Flag.withDescription("Request body"), Flag.optional),
header: Flag.String("header").pipe(
Flag.withAlias("H"),
Flag.withDescription("Request header in name:value form"),
Flag.atMost(100),
),
param: Flag.keyValuePair("param").pipe(Flag.withDescription("OpenAPI path or query parameter"), Flag.optional),
param: Flag.KeyValuePair("param").pipe(Flag.withDescription("OpenAPI path or query parameter"), Flag.optional),
},
}),
Spec.make("debug", {
@@ -122,7 +122,7 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("paths", {
description: "Show global paths (data, config, cache, state)",
params: {
name: Argument.choice("name", [
name: Argument.Literals("name", [
"db",
"home",
"data",
@@ -134,7 +134,9 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
"log",
"repos",
]).pipe(
Argument.withDescription("Print only one path: db, home, data, config, cache, state, tmp, bin, log, repos"),
Argument.withDescription(
"Print only one path: db, home, data, config, cache, state, tmp, bin, log, repos",
),
Argument.optional,
),
},
@@ -148,7 +150,7 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
description: "list providers and credentials",
params: {
...ServerParams,
format: Flag.choice("format", ["default", "json"]).pipe(
format: Flag.Literals("format", ["default", "json"]).pipe(
Flag.withDescription("Output format"),
Flag.withDefault("default"),
),
@@ -158,12 +160,12 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
description: "log in to a provider",
params: {
...ServerParams,
target: Argument.string("target").pipe(
target: Argument.String("target").pipe(
Argument.withDescription("Integration ID, name, or well-known provider URL"),
Argument.optional,
),
method: Flag.string("method").pipe(Flag.withDescription("Authentication method ID"), Flag.optional),
answer: Flag.string("answer").pipe(
method: Flag.String("method").pipe(Flag.withDescription("Authentication method ID"), Flag.optional),
answer: Flag.String("answer").pipe(
Flag.withDescription("Provider form answer (key=value; repeat for multiple fields)"),
Flag.atMost(100),
),
@@ -173,11 +175,11 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
description: "log out of a saved account",
params: {
...ServerParams,
target: Argument.string("target").pipe(
target: Argument.String("target").pipe(
Argument.withDescription("Integration ID or name"),
Argument.optional,
),
credential: Argument.string("credential").pipe(
credential: Argument.String("credential").pipe(
Argument.withDescription("Credential ID or label (opens an account picker when omitted)"),
Argument.optional,
),
@@ -187,11 +189,11 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
description: "switch the active account for an integration",
params: {
...ServerParams,
target: Argument.string("target").pipe(
target: Argument.String("target").pipe(
Argument.withDescription("Integration ID or name"),
Argument.optional,
),
credential: Argument.string("credential").pipe(
credential: Argument.String("credential").pipe(
Argument.withDescription("Credential ID or label (opens an account picker when omitted)"),
Argument.optional,
),
@@ -206,21 +208,21 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("add", {
description: "Add an MCP server to your configuration",
params: {
name: Argument.string("name").pipe(Argument.withDescription("Name of the MCP server")),
command: Argument.string("command").pipe(
name: Argument.String("name").pipe(Argument.withDescription("Name of the MCP server")),
command: Argument.String("command").pipe(
Argument.withDescription("Command and arguments for a local server, passed after --"),
Argument.variadic({ min: 0 }),
),
url: Flag.string("url").pipe(Flag.withDescription("URL for a remote MCP server"), Flag.optional),
header: Flag.keyValuePair("header").pipe(
url: Flag.String("url").pipe(Flag.withDescription("URL for a remote MCP server"), Flag.optional),
header: Flag.KeyValuePair("header").pipe(
Flag.withDescription("HTTP header for a remote server, as name=value"),
Flag.optional,
),
env: Flag.keyValuePair("env").pipe(
env: Flag.KeyValuePair("env").pipe(
Flag.withDescription("Environment variable for a local server, as name=value"),
Flag.optional,
),
global: Flag.boolean("global").pipe(
global: Flag.Boolean("global").pipe(
Flag.withDescription("Write to the global config instead of the project config"),
Flag.withDefault(false),
),
@@ -228,11 +230,11 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
}),
Spec.make("auth", {
description: "Authenticate with an OAuth-capable remote MCP server",
params: { name: Argument.string("name").pipe(Argument.withDescription("Name of the MCP server")) },
params: { name: Argument.String("name").pipe(Argument.withDescription("Name of the MCP server")) },
}),
Spec.make("logout", {
description: "Remove stored OAuth credentials for an MCP server",
params: { name: Argument.string("name").pipe(Argument.withDescription("Name of the MCP server")) },
params: { name: Argument.String("name").pipe(Argument.withDescription("Name of the MCP server")) },
}),
],
}),
@@ -242,7 +244,7 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("list", {
description: "List plugins",
params: {
builtin: Flag.boolean("builtin").pipe(
builtin: Flag.Boolean("builtin").pipe(
Flag.withDescription("Include built-in server plugins"),
Flag.withDefault(false),
),
@@ -251,13 +253,13 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("add", {
description: "Install a plugin and add it to the global configuration",
params: {
package: Argument.string("package").pipe(Argument.withDescription("npm registry or Git package specifier")),
package: Argument.String("package").pipe(Argument.withDescription("npm registry or Git package specifier")),
},
}),
Spec.make("check", {
description: "Check package plugins for updates",
params: {
target: Argument.string("target").pipe(
target: Argument.String("target").pipe(
Argument.withDescription("Configured package target"),
Argument.optional,
),
@@ -266,7 +268,7 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("update", {
description: "Update package plugins",
params: {
target: Argument.string("target").pipe(
target: Argument.String("target").pipe(
Argument.withDescription("Configured package target; omit to update all outdated plugins"),
Argument.optional,
),
@@ -275,7 +277,7 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("remove", {
description: "Remove a plugin from global configuration",
params: {
package: Argument.string("package").pipe(Argument.withDescription("configured package specifier")),
package: Argument.String("package").pipe(Argument.withDescription("configured package specifier")),
},
}),
],
@@ -288,108 +290,108 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
description: "Show shareable usage statistics",
params: {
...ServerParams,
days: Flag.integer("days").pipe(
days: Flag.Int("days").pipe(
Flag.withSchema(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),
Flag.withDescription("Show the last N days; 0 means today"),
Flag.optional,
),
year: Flag.integer("year").pipe(
year: Flag.Int("year").pipe(
Flag.withSchema(Schema.Int.check(Schema.isBetween({ minimum: 1970, maximum: 9_999 }))),
Flag.withDescription("Show a calendar year"),
Flag.optional,
),
all: Flag.boolean("all").pipe(Flag.withDescription("Show lifetime statistics"), Flag.withDefault(false)),
project: Flag.string("project").pipe(
all: Flag.Boolean("all").pipe(Flag.withDescription("Show lifetime statistics"), Flag.withDefault(false)),
project: Flag.String("project").pipe(
Flag.withDescription('Filter by project ID, or use "." for the current project'),
Flag.optional,
),
models: Flag.boolean("models").pipe(Flag.withDescription("Show model usage"), Flag.withDefault(false)),
tools: Flag.boolean("tools").pipe(Flag.withDescription("Show tool reliability"), Flag.withDefault(false)),
cost: Flag.boolean("cost").pipe(Flag.withDescription("Show cost and token details"), Flag.withDefault(false)),
full: Flag.boolean("full").pipe(Flag.withDescription("Show every detailed section"), Flag.withDefault(false)),
limit: Flag.integer("limit").pipe(
models: Flag.Boolean("models").pipe(Flag.withDescription("Show model usage"), Flag.withDefault(false)),
tools: Flag.Boolean("tools").pipe(Flag.withDescription("Show tool reliability"), Flag.withDefault(false)),
cost: Flag.Boolean("cost").pipe(Flag.withDescription("Show cost and token details"), Flag.withDefault(false)),
full: Flag.Boolean("full").pipe(Flag.withDescription("Show every detailed section"), Flag.withDefault(false)),
limit: Flag.Int("limit").pipe(
Flag.withSchema(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))),
Flag.withDescription("Number of rows in detailed sections"),
Flag.withDefault(5),
),
json: Flag.boolean("json").pipe(Flag.withDescription("Output statistics as JSON"), Flag.withDefault(false)),
json: Flag.Boolean("json").pipe(Flag.withDescription("Output statistics as JSON"), Flag.withDefault(false)),
},
}),
Spec.make("mini", {
description: "Start the minimal interactive interface",
params: {
...ServerParams,
continue: Flag.boolean("continue").pipe(
continue: Flag.Boolean("continue").pipe(
Flag.withAlias("c"),
Flag.withDescription("Continue the last session"),
Flag.withDefault(false),
),
session: Flag.string("session").pipe(
session: Flag.String("session").pipe(
Flag.withAlias("s"),
Flag.withDescription("Session ID to continue"),
Flag.optional,
),
fork: Flag.boolean("fork").pipe(
fork: Flag.Boolean("fork").pipe(
Flag.withDescription("Fork the session when continuing"),
Flag.withDefault(false),
),
replay: Flag.boolean("replay").pipe(
replay: Flag.Boolean("replay").pipe(
Flag.withDescription("Restore session history on resume and resize (disable with --no-replay)"),
Flag.optional,
),
replayLimit: Flag.integer("replay-limit").pipe(
replayLimit: Flag.Int("replay-limit").pipe(
Flag.withDescription("Limit replay to the newest N messages (default: 200)"),
Flag.optional,
),
model: Flag.string("model").pipe(
model: Flag.String("model").pipe(
Flag.withAlias("m"),
Flag.withDescription("Model to use in the format provider/model"),
Flag.optional,
),
agent: Flag.string("agent").pipe(Flag.withDescription("Agent to use"), Flag.optional),
prompt: Flag.string("prompt").pipe(Flag.withDescription("Prompt to use"), Flag.optional),
demo: Flag.boolean("demo").pipe(Flag.withDefault(false), Flag.withHidden),
agent: Flag.String("agent").pipe(Flag.withDescription("Agent to use"), Flag.optional),
prompt: Flag.String("prompt").pipe(Flag.withDescription("Prompt to use"), Flag.optional),
demo: Flag.Boolean("demo").pipe(Flag.withDefault(false), Flag.withHidden),
},
}),
Spec.make("run", {
description: "Run OpenCode with a message",
params: {
...ServerParams,
message: Argument.string("message").pipe(
message: Argument.String("message").pipe(
Argument.withDescription("Message to send"),
Argument.variadic({ min: 0 }),
),
continue: Flag.boolean("continue").pipe(
continue: Flag.Boolean("continue").pipe(
Flag.withAlias("c"),
Flag.withDescription("Continue the last session"),
Flag.withDefault(false),
),
session: Flag.string("session").pipe(
session: Flag.String("session").pipe(
Flag.withAlias("s"),
Flag.withDescription("Session ID to continue"),
Flag.optional,
),
fork: Flag.boolean("fork").pipe(
fork: Flag.Boolean("fork").pipe(
Flag.withDescription("Fork the session before continuing"),
Flag.withDefault(false),
),
model: Flag.string("model").pipe(
model: Flag.String("model").pipe(
Flag.withAlias("m"),
Flag.withDescription("Model to use in the format provider/model#variant"),
Flag.optional,
),
agent: Flag.string("agent").pipe(Flag.withDescription("Agent to use"), Flag.optional),
format: Flag.choice("format", ["default", "json"]).pipe(
agent: Flag.String("agent").pipe(Flag.withDescription("Agent to use"), Flag.optional),
format: Flag.Literals("format", ["default", "json"]).pipe(
Flag.withDescription("Output format"),
Flag.withDefault("default"),
),
file: Flag.string("file").pipe(
file: Flag.String("file").pipe(
Flag.withAlias("f"),
Flag.withDescription("File to attach to the message"),
Flag.atMost(100),
),
title: Flag.string("title").pipe(Flag.withDescription("Session title"), Flag.optional),
thinking: Flag.boolean("thinking").pipe(Flag.withDescription("Show thinking blocks"), Flag.withDefault(false)),
title: Flag.String("title").pipe(Flag.withDescription("Session title"), Flag.optional),
thinking: Flag.Boolean("thinking").pipe(Flag.withDescription("Show thinking blocks"), Flag.withDefault(false)),
...PermissionParams,
},
}),
@@ -400,13 +402,13 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
description: "List top-level sessions in the current project, newest first",
params: {
...ServerParams,
maxCount: Flag.integer("max-count").pipe(
maxCount: Flag.Int("max-count").pipe(
Flag.withAlias("n"),
Flag.withSchema(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))),
Flag.withDescription("Limit to N most recent sessions (default: 100)"),
Flag.optional,
),
format: Flag.choice("format", ["table", "json"]).pipe(
format: Flag.Literals("format", ["table", "json"]).pipe(
Flag.withDescription("Output format"),
Flag.withDefault("table"),
),
@@ -416,18 +418,18 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
description: "Delete a session and its child sessions",
params: {
...ServerParams,
sessionID: Argument.string("sessionID").pipe(Argument.withDescription("Session ID to delete")),
sessionID: Argument.String("sessionID").pipe(Argument.withDescription("Session ID to delete")),
},
}),
Spec.make("export", {
description: "Export session data as JSON",
params: {
...ServerParams,
session: Argument.string("session").pipe(
session: Argument.String("session").pipe(
Argument.withDescription("Session ID to export"),
Argument.optional,
),
sanitize: Flag.boolean("sanitize").pipe(
sanitize: Flag.Boolean("sanitize").pipe(
Flag.withDescription("Redact sensitive transcript and file data"),
Flag.withDefault(false),
),
@@ -437,8 +439,8 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
description: "Import session data from a JSON file or URL",
params: {
...ServerParams,
file: Argument.string("file").pipe(Argument.withDescription("JSON file or URL to import")),
directory: Flag.string("directory").pipe(
file: Argument.String("file").pipe(Argument.withDescription("JSON file or URL to import")),
directory: Flag.String("directory").pipe(
Flag.withDescription("Directory in which to import the session"),
Flag.optional,
),
@@ -456,8 +458,8 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("get", {
description: "Get service configuration",
params: {
key: Argument.string("key").pipe(Argument.withDescription("Service setting or env"), Argument.optional),
name: Argument.string("name").pipe(
key: Argument.String("key").pipe(Argument.withDescription("Service setting or env"), Argument.optional),
name: Argument.String("name").pipe(
Argument.withDescription("Environment variable name"),
Argument.optional,
),
@@ -466,11 +468,11 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("set", {
description: "Set service configuration",
params: {
key: Argument.string("key").pipe(Argument.withDescription("Service setting or env")),
value: Argument.string("value").pipe(
key: Argument.String("key").pipe(Argument.withDescription("Service setting or env")),
value: Argument.String("value").pipe(
Argument.withDescription("Setting value or environment variable name"),
),
nestedValue: Argument.string("env-value").pipe(
nestedValue: Argument.String("env-value").pipe(
Argument.withDescription("Environment variable value"),
Argument.optional,
),
@@ -479,8 +481,8 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("unset", {
description: "Unset service configuration",
params: {
key: Argument.string("key").pipe(Argument.withDescription("Service setting or env")),
name: Argument.string("name").pipe(
key: Argument.String("key").pipe(Argument.withDescription("Service setting or env")),
name: Argument.String("name").pipe(
Argument.withDescription("Environment variable name"),
Argument.optional,
),
@@ -497,7 +499,7 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("pair", {
description: "Show server pairing information",
params: {
url: Flag.string("url").pipe(
url: Flag.String("url").pipe(
Flag.withDescription("Advertise an external HTTP(S) server URL in the pairing QR code"),
Flag.mapTryCatch(
(value) => {
@@ -515,15 +517,15 @@ const Root = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME
Spec.make("serve", {
description: "Start the v2 API and web server",
params: {
hostname: Flag.string("hostname").pipe(Flag.optional),
port: Flag.integer("port").pipe(Flag.optional),
cors: Flag.string("cors").pipe(
hostname: Flag.String("hostname").pipe(Flag.optional),
port: Flag.Int("port").pipe(Flag.optional),
cors: Flag.String("cors").pipe(
Flag.withSchema(Schema.NonEmptyString),
Flag.withDescription("Additional allowed CORS origin (repeat for multiple origins)"),
Flag.atLeast(0),
),
service: Flag.boolean("service").pipe(Flag.withDefault(false)),
stdio: Flag.boolean("stdio").pipe(Flag.withDefault(false)),
service: Flag.Boolean("service").pipe(Flag.withDefault(false)),
stdio: Flag.Boolean("stdio").pipe(Flag.withDefault(false)),
},
}),
],
+2 -2
View File
@@ -7,8 +7,8 @@ import { Config } from "effect"
// The opencode server password: sent by clients connecting to an explicit
// --server, and adopted by a manually run or standalone server. The legacy
// name is still honored.
export const password = Config.redacted("OPENCODE_PASSWORD").pipe(
Config.orElse(() => Config.redacted("OPENCODE_SERVER_PASSWORD")),
export const password = Config.Redacted("OPENCODE_PASSWORD").pipe(
Config.orElse(() => Config.Redacted("OPENCODE_SERVER_PASSWORD")),
Config.withDefault(undefined),
)
+1 -2
View File
@@ -2,7 +2,6 @@ import type { Endpoint } from "@opencode/client/effect/service"
import { Effect } from "effect"
import path from "node:path"
import { Standalone } from "../services/standalone"
import { errorMessage } from "../util/error"
import { reportRunError, runNonInteractiveWithOptions, type RunCommandInput } from "./run"
export type V1RunCommandInput = {
@@ -54,7 +53,7 @@ export function runV1Bridge(input: V1RunCommandInput) {
)
}),
),
).catch((error) => reportRunError(input, errorMessage(error)))
).catch((error) => reportRunError(input, error instanceof Error ? error.message : String(error)))
}
function nativeInput(input: V1RunCommandInput, endpoint: Endpoint): RunCommandInput {
@@ -4,6 +4,7 @@ import { Service, type Info } from "@opencode/client/effect/service"
import path from "node:path"
import { Effect, FileSystem, Schedule, Schema } from "effect"
import { HttpServer } from "effect/unstable/http"
import { NetAddress } from "effect/unstable/net"
import { OPENCODE_VERSION } from "../version"
const infoJson = Schema.fromJsonString(Service.Info)
@@ -11,7 +12,7 @@ const encodeInfo = Schema.encodeEffect(infoJson)
const decodeInfo = Schema.decodeUnknownEffect(infoJson)
export const register = Effect.fnUntraced(function* (options: {
readonly address: HttpServer.Address
readonly address: NetAddress.SocketAddress
readonly password: string
readonly id: string
readonly file: string
+11 -6
View File
@@ -1,6 +1,5 @@
import type { LocationGetOutput, ModelRef, OpenCodeClient, SessionInfo } from "@opencode/client/promise"
import { Model } from "@opencode/schema/model"
import { errorMessage } from "./util/error"
const SESSION_PAGE_LIMIT = 50
@@ -25,7 +24,7 @@ export class SessionTargetMutationError extends Error {
override readonly name = "SessionTargetMutationError"
constructor(cause: unknown) {
super(errorMessage(cause), { cause })
super(cause instanceof Error ? cause.message : "Session target mutation failed", { cause })
}
}
@@ -126,9 +125,11 @@ async function selectSession(input: {
if (!selected) return { session: undefined, location }
return {
session: input.fork
? await input.client.session.fork({ sessionID: selected.id }, ...requestOptions(input.signal)).catch((error) => {
throw new SessionTargetMutationError(error)
})
? await input.client.session
.fork({ sessionID: selected.id }, ...requestOptions(input.signal))
.catch((error) => {
throw new SessionTargetMutationError(error)
})
: selected,
}
}
@@ -155,7 +156,11 @@ async function latestSession(
return latestSession(client, location, page.cursor.next, signal)
}
function resolveLocation(client: OpenCodeClient, location?: { directory?: string }, signal?: AbortSignal) {
function resolveLocation(
client: OpenCodeClient,
location?: { directory?: string },
signal?: AbortSignal,
) {
if (!location && !signal) return client.location.get()
if (!location) return client.location.get(undefined, { signal })
return client.location.get({ location }, ...requestOptions(signal))
+7 -7
View File
@@ -1,5 +1,6 @@
import { NodeSocket } from "@effect/platform-node"
import { Effect, Schema, Stdio, Stream } from "effect"
import { Socket } from "effect/unstable/socket"
const Response = Schema.fromJsonString(Schema.Struct({ value: Schema.NullOr(Schema.String) }))
const Port = Schema.NumberFromString.check(Schema.isInt(), Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(65535))
@@ -10,16 +11,15 @@ export const askpass = Effect.gen(function* () {
const port = yield* Schema.decodeUnknownEffect(Port)(process.env.OPENCODE_SSH_ASKPASS_PORT)
const stdio = yield* Stdio.Stdio
const socket = yield* NodeSocket.makeNet({ host: "127.0.0.1", port })
const write = yield* socket.writer
const writer = yield* socket.writer
const response = { text: "" }
yield* Effect.all(
[
socket.runString((text) =>
Effect.sync(() => {
response.text += text
}),
),
write(
Effect.gen(function* () {
const pull = yield* Socket.readerString(socket)
while (true) response.text += (yield* pull).join("")
}).pipe(Effect.catchReason("SocketError", "SocketCloseError", () => Effect.void)),
writer.write(
JSON.stringify({
token: process.env.OPENCODE_SSH_ASKPASS_TOKEN,
text: process.argv.slice(2).join(" "),
+2 -1
View File
@@ -4,6 +4,7 @@ import { Global } from "@opencode/util/global"
import { OPENCODE_VERSION } from "../src/version"
import { expect, test } from "bun:test"
import { Effect, Schema } from "effect"
import { NetAddress } from "effect/unstable/net"
import fs from "node:fs/promises"
import os from "node:os"
import path from "node:path"
@@ -501,7 +502,7 @@ test("service registration replaces a stale owner with the bound address", async
try {
const cleanup = await Effect.runPromise(
ServiceRegistration.register({
address: { _tag: "TcpAddress", hostname: "127.0.0.1", port: 4321 },
address: NetAddress.inetAddressFromIpStringUnsafe("127.0.0.1", 4321),
password: "secret",
id: "owner",
file: registration,
+1 -1
View File
@@ -37,7 +37,7 @@
"@opencode/protocol": "workspace:*"
},
"peerDependencies": {
"effect": "4.0.0-rc.112",
"effect": "4.0.0-rc.115",
"solid-js": ">=1.9.0"
},
"peerDependenciesMeta": {
@@ -330,8 +330,7 @@ export function make(options: ClientOptions) {
}
const responseError = async (response: Response, descriptor: RequestDescriptor): Promise<never> => {
if (descriptor.declaredStatuses.includes(response.status))
throw declared((await json(response)) as DeclaredErrorBody)
if (descriptor.declaredStatuses.includes(response.status)) throw await json(response)
try {
await response.body?.cancel()
} catch {}
@@ -2201,19 +2200,6 @@ async function json(response: Response): Promise<unknown> {
}
}
type DeclaredErrorBody = {
readonly _tag?: string
readonly message?: string
readonly data?: { readonly message?: string }
}
/** Throw declared error bodies as Errors. The body's fields stay on the error, so narrowing on `_tag` or `name` still works. */
function declared(body: DeclaredErrorBody) {
const error = Object.assign(new Error(body.message ?? body.data?.message), body)
if (body._tag) error.name = body._tag
return error
}
function isContentType(response: Response, expected: string) {
return response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase() === expected
}
@@ -296,7 +296,7 @@ export type ProjectIcon = { url?: string; override?: string; color?: string }
export type ProjectCommands = { start?: string }
export type ProjectTime = { created: number; updated: number; active: number }
export type ProjectTime = { created: number; updated: number }
export type PermissionSource = { type: "tool"; messageID: string; id: string }
+1 -1
View File
@@ -1788,7 +1788,7 @@ export function createData(config: CreateDataInput) {
},
project: {
list() {
return Object.values(store.project.info).toSorted((a, b) => b.time.active - a.time.active)
return Object.values(store.project.info).toSorted((a, b) => b.time.updated - a.time.updated)
},
get(projectID: string) {
return store.project.info[projectID]
-40
View File
@@ -151,46 +151,6 @@ test("vcs.diff exposes unavailable comparisons as errors, not empty diffs", asyn
})
})
test("declared errors are thrown as Error instances that keep the body", async () => {
const client = OpenCode.make({
baseUrl: "http://localhost:3000",
fetch: async () =>
Response.json(
{ _tag: "InvalidRequestError", message: "Incompatible auth server", kind: "integration_authorization" },
{ status: 400 },
),
})
const error = await client.integration.oauth
.connect({ integrationID: "mcp_test", methodID: "oauth", location: { directory: "/repo" } })
.then(
() => undefined,
(cause: unknown) => cause,
)
expect(error).toBeInstanceOf(Error)
if (!(error instanceof Error)) throw error
expect(error.message).toBe("Incompatible auth server")
expect(error.name).toBe("InvalidRequestError")
expect(error.stack).toContain("InvalidRequestError: Incompatible auth server")
expect(error).toMatchObject({ _tag: "InvalidRequestError", kind: "integration_authorization" })
})
test("declared errors with a data envelope read the nested message", async () => {
const client = OpenCode.make({
baseUrl: "http://localhost:3000",
fetch: async () =>
Response.json({ name: "WorktreeError", data: { message: "Worktree directory unavailable" } }, { status: 400 }),
})
const error = await client.worktree.create({ projectID: "prj_test" }).then(
() => undefined,
(cause: unknown) => cause,
)
expect(error).toBeInstanceOf(Error)
if (!(error instanceof Error)) throw error
expect(error.message).toBe("Worktree directory unavailable")
expect(error.name).toBe("WorktreeError")
expect(error).toMatchObject({ name: "WorktreeError", data: { message: "Worktree directory unavailable" } })
})
test("project.update uses the global project contract", async () => {
let request: Request | undefined
const project = {
+22 -46
View File
@@ -41,8 +41,8 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
- [x] A trailing comma after a rest parameter is a syntax error, with or without `"use strict"`.
- [x] A program that begins with `"use strict"` rejects `yield` as an identifier and duplicate parameter names at
parse time. Without it, `yield` is an ordinary binding.
- [x] Duplicate parameter names in non-strict code bind the last parameter, as in JS (`function f(a, a)` called
with `(1, 2)` sees `a === 2`).
- [ ] Duplicate parameter names in non-strict code throw when the function is called, instead of binding the last
parameter as JavaScript does.
## Values and literals
@@ -52,15 +52,12 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
- [x] Object literals with shorthand, computed string/number keys, and spread following ToObject: data objects and
arrays copy own enumerable keys, strings copy index keys, and other values contribute nothing.
- [x] Template literals with interpolation.
- [x] Tagged templates: a tag applied to a template literal is called as `tag(strings, ...values)`, with the tag read
like a callee so a member tag keeps its receiver. `strings` is an array of the cooked text with a read-only `raw`
array of the source text; an invalid escape such as `\unicode` cooks to `undefined`. One template object per
site, as in JS, but it is not frozen: `strings[0] = "x"` succeeds here where JS throws.
- [x] Regular-expression literals.
- [x] `NaN` and `Infinity` globals.
- [ ] BigInt literals and in-interpreter BigInt arithmetic; BigInt remains invalid at JSON-like host boundaries.
- [ ] Arbitrary Symbol primitive values and symbol-keyed properties. The confined `Symbol.iterator` and
`Symbol.asyncIterator` keys are available only for the iterator protocols.
- [ ] Tagged-template calls.
- [ ] Getter and setter definitions in object literals.
## Bindings and destructuring
@@ -89,8 +86,7 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
sources are rejected.
- [x] Destructuring reads through the prototype chain like member access: `const { constructor } = error` and
`const { slice } = values` find the inherited built-in.
- [x] Any assignment target as a `for...in` head, like `for...of`: `for (x.y in obj)`, `for (a[i++] in obj)`, and
destructuring patterns.
- [ ] Member expressions as `for...in` targets (`for (x.y in obj)`).
## Statements and control flow
@@ -138,20 +134,11 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
arrow function.
- [x] Promise-returning string replacers are coerced synchronously to `"[object Promise]"`, like JavaScript; they are
not automatically awaited.
- [x] `this` in non-arrow functions is the call's receiver: `obj.m()` and `obj["m"]()` see `obj`, a bare or detached
call (`f()`, `const m = obj.m; m()`, `(0, obj.m)()`) sees `undefined`, as in strict JS. Arrows read the enclosing
function's `this`. Program code has no receiver, so top-level `this` is `undefined`, as in a module.
- [x] `arguments` in non-arrow functions: an unmapped array-like of the call's arguments (`length`, indexes, spread,
`Array.from`), tagged `[object Arguments]` and not an Array. A parameter named `arguments` shadows it; arrows
read the enclosing function's. `callee` and `caller` are absent rather than poisoned.
- [x] `Function.prototype.call`, `apply`, and `bind` on program functions and built-ins:
`Array.prototype.push.call(arr, 1)`, `Math.max.apply(null, values)`, `fn.bind(obj, first)`. `apply` accepts an
array, an array-like object, or `null`/`undefined`. A bound function is named `bound f`, has its remaining
`length`, and is not constructible.
- [x] `JSON.parse` revivers and `JSON.stringify` function replacers see the holder object as `this`.
- [ ] The optional `thisArg` of iteration methods (`map`, `forEach`, `Map.prototype.forEach`, `Array.from`, …) is
accepted but not yet passed as `this`; callbacks run with `this` undefined.
- [x] The optional `thisArg` of iteration methods is accepted and ignored: CodeMode functions have no `this`, so
ignoring it matches JS arrow-function semantics exactly.
- [ ] `this` in non-arrow CodeMode functions and callbacks.
- [ ] User-defined constructor calls.
- [ ] `Function.prototype.call`, `apply`, and `bind` for CodeMode functions.
- [ ] Classes and private fields.
- [x] Functions are objects: they hold own properties (`fn.count = 1`), enumerate them, and expose read-only `name`
and `length`. Names follow JavaScript's NamedEvaluation: declarations, named expressions, bindings,
@@ -184,7 +171,7 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
yielded promises; mixed async request queues; sync and async `yield*` forwarding; malformed methods/results;
and declaration, expression, and object-method forms with closure and parameter behavior. The adapted suite
deliberately skips Test262 variants whose observation mechanism requires unsupported getter definitions,
proxies, prototype inspection or mutation, classes, or arbitrary symbols. It also skips tests
proxies, prototype inspection or mutation, non-arrow `this`, classes, or arbitrary symbols. It also skips tests
asserting exact promise reaction-turn counts beyond the observable ordering guarantee documented below. These
are interpreter-surface boundaries, not claims that the corresponding full Test262 families pass unchanged.
@@ -214,18 +201,10 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
creates a hole without changing its length. Deleting a non-configurable property (`length`) or
assigning a read-only one (`Math.PI`, `fn.name`) throws a `TypeError`, as in strict mode. `delete` of a
non-reference (`delete 0`, `delete f()`) evaluates the operand and is `true`; `delete x` on a variable throws.
- [x] Coercion helpers and template interpolation accept functions and namespaces: `String(fn)` and `${fn}` give
`"[object Function]"` rather than the source text, `isNaN(fn)` is `true`.
- [ ] Operators other than `===`/`!==`, `switch` discriminants and cases, and `Object.is` applied to a function,
promise, generator, tool reference, or any object holding one anywhere inside; JavaScript compares by identity or
coerces (`fn == null` is `false`, `fn + ""` is its source text), the interpreter throws
`TypeError: Binary operators require data values.` The check walks both operands' whole object graphs, so
`rows == null` on a large array is slow where `rows === null` is not.
- [ ] ToPrimitive on program objects: operators, `Number`/`String`, `Error(message)`, `parseInt` radix, multi-argument
`Date` construction and `Date.UTC`, and numeric built-in arguments (`Math.max`, `at`, `indexOf` start) should call
the object's own `valueOf`/`toString` in spec order and surface their throws. Today they use the built-in form
(`NaN`, `"[object Object]"`) and ignore own methods. Date setters and one-argument `Date` construction already
follow ToPrimitive.
- [ ] Operators, `switch` discriminants, template interpolation, and coercion helpers such as `String` and `isNaN`
applied to functions and namespaces; JavaScript coerces them, the interpreter rejects non-data operands.
- [ ] ToPrimitive on object operands: operators, `Error(message)`, `Date` arguments, and `parseInt` radix should call
`valueOf`/`toString` in spec order and surface their throws.
- [x] Property keys follow ToPropertyKey: `x[null]`, `x[true]`, and objects (via their built-in string form) become
string keys.
@@ -270,7 +249,7 @@ reject }` object.
- [x] Recursive assimilation of objects with an own callable `then` field across `Promise.resolve`, combinators,
constructors, reactions, `finally`, `await`, and async returns. Thenable methods run deferred, receive
first-call-wins resolve/reject functions, and ignore throws after settlement. Inherited/accessor `then` fields
remain outside the supported object model.
and a JavaScript `this` receiver remain outside the supported object/function model.
- [x] Dotted tool names are canonicalized into namespace paths; a path can be both callable and a namespace, and the
last tool supplied for a canonical path wins.
- [x] Tool path segments may be named `constructor`, `prototype`, or `__proto__` because paths use inert Map keys.
@@ -364,12 +343,10 @@ reject }` object.
native JS, `split(undefined)` returns the whole string, and `includes`/`startsWith`/`endsWith` reject regular
expressions with a native-style `TypeError`. Opaque runtime references still reject as data errors, and
`repeat` still requires a finite non-negative count.
- [x] Native no-argument parity for `match()`, `matchAll()`, and `search()`; all behave as an empty pattern.
- [x] `String.raw`, on a template object or any `{ raw }` object; raw strings and substitutions coerce through their own
`toString`.
- [x] `match`, `matchAll`, `search`, and `split` read any non-RegExp argument as a pattern string, as `new RegExp(arg)`
would: `"a1b".match(1)` matches `/1/`, `search(null)` looks for `"null"`, and `undefined` is the empty pattern.
Objects use their built-in string form until ToPrimitive lands.
- [x] Native no-argument parity for `match()`, `matchAll()`, and `search()`; all behave as an empty pattern. Present
arguments must still be a regular expression or string pattern.
- [ ] `String.raw`.
- [ ] `match`, `search`, and `split` accept any value and coerce it (objects via `toString`), like JavaScript.
## Numbers and Math
@@ -401,9 +378,9 @@ reject }` object.
- [x] `JSON.parse` and `JSON.stringify` for supported data objects.
- [x] Numeric/string indentation for `JSON.stringify`.
- [x] `JSON.parse` reviver callbacks, including postorder traversal, deletion through `undefined`, and root replacement.
Revivers receive `(key, value)` with the holder as `this`.
Revivers receive `(key, value)` but no `this` holder because CodeMode functions intentionally have no `this`.
- [x] `JSON.stringify` function and array replacers. Function replacers receive `(key, value)` in preorder, including
the root, with the holder as `this`. Array replacers preserve requested property order, deduplicate names, coerce
the root, but no `this` holder. Array replacers preserve requested property order, deduplicate names, coerce
number primitives, and ignore non-string/non-number entries. Primitive wrapper entries remain unsupported.
- [x] Captured `console.log`, `console.info`, `console.debug`, `console.warn`, and `console.error`. An Error prints as
`Error.prototype.toString` would show it (`Error: boom`), wherever it appears in the logged value.
@@ -429,9 +406,8 @@ reject }` object.
- [x] `toLocaleString`, `toLocaleDateString`, and `toLocaleTimeString` always format as `en-US` in UTC
(`"1/1/1970, 12:00:00 AM"`) so output does not depend on the host.
- [x] Native one-argument Date coercion for supported values, including booleans, null, arrays, and plain objects.
- [x] Date setters and one-argument construction coerce object arguments through their own `valueOf`/`toString` and
surface their throws.
- [ ] Multi-argument construction and `Date.UTC` coerce object arguments the same way (see ToPrimitive above).
- [ ] Date setters and multi-argument construction coerce object arguments through `valueOf`/`toString` and surface
their throws.
- [x] Native Date loose-equality and default primitive-coercion semantics, using CodeMode's deterministic ISO string
representation for the string primitive.
- [x] Native `RangeError` branding for invalid `toISOString()` calls.
+2 -2
View File
@@ -24,7 +24,7 @@ import { typeofValue } from "./interpreter/references.js"
export type Json = Schema.Json
type Replacer<R> = (args: Array<Value>, holder: Obj) => Effect.Effect<Value, unknown, R>
type Replacer<R> = (args: Array<Value>) => Effect.Effect<Value, unknown, R>
/**
* What `JSON.stringify` would serialize for a program value, as host JSON: `toJSON` is honored, functions and
@@ -60,7 +60,7 @@ const walk = <R>(
const settled = raw instanceof PromiseObj ? yield* ctx.await(raw) : raw
const toJSON = settled instanceof Obj ? get(settled, "toJSON") : undefined
const own = toJSON instanceof Callable ? yield* ctx.call(toJSON, settled, [key]) : settled
const value = replacer === undefined ? own : yield* replacer([key, own], holder)
const value = replacer === undefined ? own : yield* replacer([key, own])
if (value === undefined || typeofValue(value) === "function") return undefined
if (typeof value === "number") return Number.isFinite(value) ? value : null
if (value === null || typeof value === "string" || typeof value === "boolean") return value
@@ -78,7 +78,7 @@ export const applyCollectionCallback = <R>(
ctx: Interpreter<R>,
callback: Value,
name: string,
): ((args: Array<Value>, thisValue?: Value) => Effect.Effect<Value, unknown, R>) => {
): ((args: Array<Value>) => Effect.Effect<Value, unknown, R>) => {
if (!isSupportedCallback(callback)) {
if (typeofValue(callback) === "function") {
throw typeError(
@@ -87,5 +87,5 @@ export const applyCollectionCallback = <R>(
}
throw typeError(`${name} expects a function callback.`)
}
return (callbackArgs, thisValue) => ctx.call(callback, thisValue, callbackArgs)
return (callbackArgs) => ctx.call(callback, undefined, callbackArgs)
}
+2 -29
View File
@@ -1,5 +1,5 @@
import { Effect } from "effect"
import { Arr, Callable, coerceToInteger, coerceToString, get, Obj, type Value } from "./objects.js"
import type { Value } from "./objects.js"
import { arrayGlobal } from "../stdlib/array.js"
import { textDecoderGlobal, textEncoderGlobal, uint8ArrayGlobal } from "../stdlib/bytes.js"
import { mapGlobal, setGlobal } from "../stdlib/collections.js"
@@ -19,7 +19,7 @@ import { base64Global, cryptoGlobal } from "../stdlib/web.js"
import { ToolReference } from "../tool-runtime.js"
import { errorGlobal } from "./errors.js"
import { errorTypes } from "./intrinsics.js"
import { constants, constructor, methods, native, receiver } from "./native.js"
import { constants, constructor, native } from "./native.js"
import { AsyncIteratorSymbol, IteratorSymbol, typeError } from "./model.js"
import { generatorGlobals } from "./generators.js"
import { promiseGlobal } from "./promises.js"
@@ -31,25 +31,6 @@ const functionGlobal = <R>(ctx: Interpreter<R>) => {
Effect.sync(() => {
throw typeError("The Function constructor is not supported; write the function inline.")
})
const target = (thisValue: Value, method: string) => receiver(Callable, thisValue, `Function.prototype.${method}`)
methods(ctx.builtins, ctx.builtins.Function, [
["call", 1, (thisValue, args) => ctx.call(target(thisValue, "call"), args[0], args.slice(1))],
["apply", 2, (thisValue, args) => ctx.call(target(thisValue, "apply"), args[0], listFromArrayLike(args[1]))],
[
"bind",
1,
(thisValue, args) => {
const fn = target(thisValue, "bind")
const bound = args.slice(1)
const length = get(fn, "length")
return native<R>(ctx.builtins, {
name: `bound ${coerceToString(get(fn, "name"))}`,
length: Math.max(0, (typeof length === "number" ? length : 0) - bound.length),
call: (_, rest) => ctx.call(fn, args[0], [...bound, ...rest]),
})
},
],
])
return constructor<R>(ctx.builtins, ctx.builtins.Function, {
name: "Function",
length: 1,
@@ -58,14 +39,6 @@ const functionGlobal = <R>(ctx: Interpreter<R>) => {
})
}
// CreateListFromArrayLike: `apply` reads `length` and the indexed properties of any object.
const listFromArrayLike = (value: Value): Array<Value> => {
if (value === undefined || value === null) return []
if (value instanceof Arr) return [...value.items]
if (!(value instanceof Obj)) throw typeError("Function.prototype.apply expects an array-like argument list.")
return Array.from({ length: coerceToInteger(get(value, "length")) }, (_, index) => get(value, String(index)))
}
const symbolGlobal = <R>(ctx: Interpreter<R>) => {
const symbol = native<R>(ctx.builtins, {
name: "Symbol",
@@ -32,7 +32,6 @@ import type {
Statement,
Super,
SwitchStatement,
TaggedTemplateExpression,
Literal,
TemplateLiteral,
ThrowStatement,
@@ -70,7 +69,6 @@ import {
assign,
Callable,
define,
frozen,
get,
hostCursor,
IteratorObj,
@@ -81,7 +79,6 @@ import {
keys,
Native,
parseArrayIndex,
Arguments,
Arr,
Fn,
GeneratorObj,
@@ -273,8 +270,6 @@ export class Interpreter<R> {
readonly pending: Pending<R>
readonly builtins: Builtins
readonly logs: Array<string>
/** Template objects by site: a tag sees the same `strings` array every time its literal is evaluated, as in JS. */
readonly templates = new WeakMap<TaggedTemplateExpression, Arr>()
private readonly root: Frame<R>
constructor(options: {
@@ -288,8 +283,7 @@ export class Interpreter<R> {
this.pending = options.pending
this.builtins = options.builtins
this.logs = options.logs ?? []
// Program code has no receiver: top-level `this` is undefined, as in a module.
const globalScope = new Map<string, Binding>([["this", { mutable: false, value: undefined }]])
const globalScope = new Map<string, Binding>()
// Calling back into the program never reads frame state, so any frame serves; the root is always alive.
this.root = new Frame(this, new ScopeStack([globalScope]))
for (const [name, value] of [...globals(this), ...(options.globals?.(this) ?? [])]) {
@@ -470,7 +464,6 @@ class Frame<R> {
this.scopes.capture(),
node.async,
node.generator,
node.type === "ArrowFunctionExpression",
)
// Each generator function gets its own prototype, so `g() instanceof g` holds as in JS.
if (node.generator)
@@ -940,10 +933,10 @@ class Frame<R> {
const keys = self.enumerableKeys(right, node.right)
if (left.type === "RestElement" || left.type === "AssignmentPattern") {
if (left.type !== "Identifier" && left.type !== "VariableDeclaration") {
throw typeError("Unsupported for...in binding.", left)
}
const assignment = left.type === "VariableDeclaration" ? undefined : left
const assignmentName = left.type === "Identifier" ? left.name : undefined
for (const key of keys) {
const result = yield* Effect.gen(function* () {
@@ -953,8 +946,8 @@ class Frame<R> {
yield* self.declarePattern(declared.pattern, key, declared.mutable, left, true)
} else if (declared) {
yield* self.assignPattern(declared.pattern, key, left)
} else if (assignment) {
yield* self.assignPattern(assignment, key, left)
} else if (assignmentName) {
self.scopes.set(assignmentName, key, left)
}
return yield* self.evaluateStatement(node.body)
}).pipe(
@@ -1267,8 +1260,6 @@ class Frame<R> {
}
case "Identifier":
return Effect.sync(() => this.scopes.get(node.name, node))
case "ThisExpression":
return Effect.sync(() => this.scopes.get("this", node))
case "BinaryExpression":
return this.evaluateBinaryExpression(node)
case "LogicalExpression":
@@ -1304,8 +1295,6 @@ class Frame<R> {
return this.evaluateArrayExpression(node)
case "TemplateLiteral":
return this.evaluateTemplateLiteral(node)
case "TaggedTemplateExpression":
return this.evaluateTaggedTemplate(node)
case "ConditionalExpression":
return this.evaluateConditionalExpression(node)
case "UpdateExpression":
@@ -1622,7 +1611,7 @@ class Frame<R> {
}
return yield* self.createToolCallPromise(callable.path, args)
}
if (callable instanceof Fn) return yield* self.invokeFunction(callable, thisValue, args, node)
if (callable instanceof Fn) return yield* self.invokeFunction(callable, args, node)
if (callable instanceof Native) {
return yield* self.native(() => (callable as Native<R>).call(thisValue, args), node)
}
@@ -1664,32 +1653,19 @@ class Frame<R> {
}
// A callback invoked by a built-in runs below the call that invoked the built-in, so the deeper of the two counts.
invokeFunction(fn: Fn, thisValue: Value, args: Array<Value>, node?: AstNode): Effect.Effect<Value, unknown, R> {
invokeFunction(fn: Fn, args: Array<Value>, node?: AstNode): Effect.Effect<Value, unknown, R> {
const self = this
return Effect.flatMap(CallSite, (site) => {
const depth = Math.max(self.depth, site.depth) + 1
if (depth > MAX_CALL_DEPTH) throw rangeError("Maximum call stack size exceeded", node)
const invocation = new Frame(this.ctx, new ScopeStack([...fn.capturedScopes, new Map()]), depth)
const paramScope = invocation.scopes.current()
// `this` and `arguments` are scope bindings so arrows resolve them lexically; a parameter named
// `arguments` shadows the object, as in JS.
if (!fn.arrow) {
paramScope.set("this", { mutable: false, value: thisValue, initialized: true })
paramScope.set("arguments", {
mutable: true,
value: new Arguments(self.ctx.builtins.Object, [...args]),
initialized: true,
})
}
// Seed all parameters first so defaults cannot fall through to same-named outer bindings.
const paramScope = invocation.scopes.current()
for (const parameter of fn.parameters) {
for (const name of collectPatternNames(parameter)) {
paramScope.set(name, { mutable: true, value: undefined, initialized: false })
}
}
const parameters = fn.parameters.map((parameter) =>
parameter.type === "Identifier" ? parameter.name : undefined,
)
const bind = Effect.gen(function* () {
for (const [index, parameter] of fn.parameters.entries()) {
if (parameter.type === "RestElement") {
@@ -1702,8 +1678,6 @@ class Frame<R> {
)
break
}
// A sloppy simple parameter list may repeat a name; the last occurrence wins, as in JS.
if (parameter.type === "Identifier" && parameters.lastIndexOf(parameter.name) !== index) continue
yield* invocation.declarePattern(parameter, args[index], true, parameter, true)
}
})
@@ -2032,7 +2006,7 @@ class Frame<R> {
return Effect.gen(function* () {
for (let index = 0; index < quasis.length; index += 1) {
const quasi = quasis[index]!
// acorn only omits `cooked` for invalid escapes, which are a parse error outside a tagged template.
// acorn only omits `cooked` for invalid escapes in tagged templates, which are unsupported.
if (typeof quasi.value.cooked !== "string") {
throw typeError("Invalid template literal quasi.", quasi)
}
@@ -2050,41 +2024,6 @@ class Frame<R> {
})
}
// `tag\`a${x}b\`` is `tag(strings, x)`: the tag is read like a callee (a member keeps its receiver), the
// substitutions are evaluated in order, and `strings` carries the escaped source as `strings.raw`.
private evaluateTaggedTemplate(node: TaggedTemplateExpression): Effect.Effect<Value, unknown, R> {
const self = this
return Effect.gen(function* () {
const { callable, thisValue } =
node.tag.type === "MemberExpression"
? yield* self.readMethod(node.tag)
: { callable: yield* self.evaluateExpression(node.tag), thisValue: undefined }
const strings = self.ctx.templates.get(node) ?? self.createTemplateObject(node)
const values = yield* Effect.forEach(node.quasi.expressions, (expression) => self.evaluateExpression(expression))
return yield* self.call(callable, thisValue, [strings, ...values], node, node.tag)
})
}
private createTemplateObject(node: TaggedTemplateExpression): Arr {
const array = this.ctx.builtins.Array
// An invalid escape such as `\unicode` cooks to `undefined` and survives only in `raw`.
const strings = new Arr(
array,
node.quasi.quasis.map((quasi) => quasi.value.cooked ?? undefined),
)
define(
strings,
"raw",
new Arr(
array,
node.quasi.quasis.map((quasi) => quasi.value.raw),
),
frozen,
)
this.ctx.templates.set(node, strings)
return strings
}
private evaluateConditionalExpression(node: ConditionalExpression): Effect.Effect<Value, unknown, R> {
return Effect.flatMap(this.evaluateExpression(node.test), (test) =>
this.evaluateExpression(test ? node.consequent : node.alternate),
+1 -1
View File
@@ -72,7 +72,7 @@ export const uriError = failure("URIError")
// Orient the agent rather than enumerate JavaScript; interpreter-support.md is the full matrix.
export const supportedSyntaxMessage =
"This is a restricted JavaScript-like language. Supported: plain and async functions, data literals, destructuring, standard control flow, await and Promise, and built-ins such as Array, Object, Math, JSON, Date, RegExp, Map, Set, and URL. Unsupported: classes, getters/setters, BigInt, and custom Symbols. Use plain functions and data objects instead."
"This is a restricted JavaScript-like language. Supported: plain and async functions, data literals, destructuring, standard control flow, await and Promise, and built-ins such as Array, Object, Math, JSON, Date, RegExp, Map, Set, and URL. Unsupported: classes, this, getters/setters, tagged templates, BigInt, and custom Symbols. Use plain functions and data objects instead."
export const unsupportedSyntax = (kind: string, node: AstNode): PendingThrow =>
new PendingThrow(
+1 -8
View File
@@ -90,7 +90,7 @@ export class Obj {
}
export class Arr extends Obj {
override readonly tag: string = "Array"
override readonly tag = "Array"
constructor(
proto: Obj,
readonly items: Array<Value> = [],
@@ -162,19 +162,12 @@ export class Fn extends Callable {
readonly capturedScopes: Array<Map<string, Binding>>,
readonly async: boolean,
readonly generator: boolean,
/** Arrows have no `this` or `arguments` of their own; they read the enclosing function's. */
readonly arrow: boolean,
) {
const optional = parameters.findIndex((p) => p.type === "AssignmentPattern" || p.type === "RestElement")
super(proto, name, optional === -1 ? parameters.length : optional)
}
}
/** The strict `arguments` object: an unmapped copy of the call's arguments that is not an Array. */
export class Arguments extends Arr {
override readonly tag = "Arguments"
}
export type NativeCall<R> = (thisValue: Value, args: Array<Value>) => Effect.Effect<Value, unknown, R>
export type NativeConstruct<R> = (args: Array<Value>, newTarget: Callable) => Effect.Effect<Value, unknown, R>
+1 -2
View File
@@ -6,7 +6,6 @@ import {
define,
get,
hidden,
Arguments,
Arr,
GeneratorObj,
hostIterator,
@@ -119,7 +118,7 @@ export const arrayGlobal = <R>(ctx: Interpreter<R>) => {
construct: (args, newTarget) => Effect.sync(() => construct(args, prototypeFrom(newTarget, proto))),
})
methods(builtins, array, [
["isArray", 1, (_, args) => args[0] instanceof Arr && !(args[0] instanceof Arguments)],
["isArray", 1, (_, args) => args[0] instanceof Arr],
["of", 0, (_, args) => wrap([...args])],
["from", 1, (_, args) => arrayFrom(ctx, args)],
])
+1 -1
View File
@@ -40,7 +40,7 @@ const parse = <R>(ctx: Interpreter<R>, args: Array<Value>): Effect.Effect<Value,
else set(value, name, revived)
}
}
return yield* apply([key, value], holder)
return yield* apply([key, value])
})
return visit(record(ctx.builtins.Object, { "": parsed }), "")
}
+13 -8
View File
@@ -33,16 +33,21 @@ const escapeRegexHint =
'To match special characters like ( ) [ ] { } + * ? . literally, escape them with a backslash (e.g. "\\\\(") or test for them with String.includes instead.'
export const toHostRegex = (arg: Value, method: string, extraFlags = ""): RegExp => {
// Native parity: an undefined pattern behaves as an empty pattern.
if (arg === undefined) return new RegExp("", extraFlags)
if (arg instanceof RegExpObj) return arg.regex
// Anything else is a pattern string, as `new RegExp(arg)` would read it: undefined is the empty pattern.
const source = arg === undefined ? "" : coerceToString(arg)
try {
return new RegExp(source, extraFlags)
} catch (error) {
throw syntaxError(
`String.${method} received the string ${JSON.stringify(source)}, which is not a valid regular expression pattern (${regexFailureReason(error)}). ${escapeRegexHint}`,
)
if (typeof arg === "string") {
try {
return new RegExp(arg, extraFlags)
} catch (error) {
throw syntaxError(
`String.${method} received the string ${JSON.stringify(arg)}, which is not a valid regular expression pattern (${regexFailureReason(error)}). ${escapeRegexHint}`,
)
}
}
throw typeError(
`String.${method} expects a regular expression (a /pattern/flags literal or new RegExp(...)) or a string pattern, not ${arg === null ? "null" : typeof arg}.`,
)
}
export const matchToValue = (builtins: Builtins, match: RegExpMatchArray): Arr => {
+1 -27
View File
@@ -4,20 +4,17 @@ import { checkArrayLength, checkStringLength } from "../interpreter/limits.js"
import { invalidData, IteratorSymbol, rangeError, typeError } from "../interpreter/model.js"
import {
define,
get,
hidden,
Arr,
hostIterator,
Obj,
RegExpObj,
record,
coerceToInteger,
coerceToNumber,
coerceToString,
type Value,
} from "../interpreter/objects.js"
import { containsOpaqueReference, typeofValue } from "../interpreter/references.js"
import { applyCollectionCallback, isSupportedCallback, toPrimitiveString } from "../interpreter/callback.js"
import { applyCollectionCallback, isSupportedCallback } from "../interpreter/callback.js"
import type { Interpreter } from "../interpreter/interpreter.js"
import { matchToValue, toHostRegex } from "./regexp.js"
import { coercion } from "./value.js"
@@ -101,29 +98,6 @@ export const stringGlobal = <R>(ctx: Interpreter<R>) => {
methods(builtins, string, [
codeUnits("fromCharCode", String.fromCharCode),
codeUnits("fromCodePoint", String.fromCodePoint),
[
"raw",
1,
(_, args) => {
const template = args[0]
const raw = template instanceof Obj ? get(template, "raw") : undefined
if (!(raw instanceof Obj)) throw typeError("String.raw expects a template object with a raw array.")
const count = Math.max(0, coerceToInteger(get(raw, "length")))
checkArrayLength(count)
// Each literal is followed by its substitution, except the last literal, or when substitutions run out.
const parts = Array.from({ length: count }, (_, index) =>
index + 1 < count && index + 1 < args.length ? [get(raw, index), args[index + 1]] : [get(raw, index)],
).flat()
return Effect.map(
Effect.forEach(parts, (part) => toPrimitiveString(ctx, part)),
(strings) => {
const output = strings.join("")
checkStringLength(output.length)
return output
},
)
},
],
])
const self = (thisValue: Value, name: string): string => {
+24 -15
View File
@@ -1,4 +1,4 @@
import { JsonPointer, Schema } from "effect"
import { JsonPointer, Schema, SchemaAST } from "effect"
import type { Tool, JsonSchema, SchemaType } from "./tool.js"
const isEffectSchema = (schema: SchemaType): schema is Schema.Decoder<unknown> & Schema.Top => Schema.isSchema(schema)
@@ -12,8 +12,14 @@ const renderKey = (name: string): string => (identifierSegment.test(name) ? name
const effectNumberSentinel = (schema: JsonSchema) =>
schema.type === "string" &&
Array.isArray(schema.enum) &&
schema.enum.length === 1 &&
(schema.enum[0] === "NaN" || schema.enum[0] === "Infinity" || schema.enum[0] === "-Infinity")
(schema.enum.length === 1 ||
(schema.enum.length === 3 && ["NaN", "Infinity", "-Infinity"].every((value) => schema.enum?.includes(value)))) &&
schema.enum.every((value) => value === "NaN" || value === "Infinity" || value === "-Infinity")
const definitionName = (ref: string): string | undefined => {
const tokens = JsonPointer.parseUriFragment(ref)
return tokens?.length === 2 && (tokens[0] === "$defs" || tokens[0] === "definitions") ? tokens[1] : undefined
}
const intersection = (members: ReadonlyArray<string>): string => {
const concrete = members.filter((member) => member !== "unknown")
@@ -38,8 +44,7 @@ const hasUnresolvedRef = (
if (visited.has(schema)) return false
const nextVisited = new Set([...visited, schema])
if (schema.$ref !== undefined) {
const segment = schema.$ref.match(/^#\/(?:\$defs|definitions)\/([^/]+)$/)?.[1]
const name = segment === undefined ? undefined : JsonPointer.unescapeToken(segment)
const name = definitionName(schema.$ref)
if (name === undefined || definitions[name] === undefined || seen.has(name)) return true
if (hasUnresolvedRef(definitions[name], definitions, new Set([...seen, name]), nextVisited)) return true
}
@@ -130,8 +135,7 @@ const renderSchema = (
? ctx
: { ...ctx, definitions: { ...ctx.definitions, ...(schema.definitions ?? {}), ...(schema.$defs ?? {}) } }
if (schema.$ref) {
const segment = schema.$ref.match(/^#\/(?:\$defs|definitions)\/([^/]+)$/)?.[1]
const name = segment === undefined ? undefined : JsonPointer.unescapeToken(segment)
const name = definitionName(schema.$ref)
if (!name || !nested.definitions[name] || seen.has(name)) return "unknown"
return intersection([
renderSchema(nested.definitions[name], nested, depth, new Set([...seen, name])),
@@ -203,7 +207,7 @@ const renderSchema = (
export const toTypeScript = (schema: Schema.Top, decoded = false, pretty = false): string => {
try {
const visible = decoded ? Schema.toType(schema) : schema
const document = Schema.toJsonSchemaDocument(visible) as {
const document = Schema.toJsonSchemaDocument(visible, { onExcessProperty: "error" }) as {
readonly schema: JsonSchema
readonly definitions?: Readonly<Record<string, JsonSchema>>
}
@@ -230,7 +234,7 @@ export type InputProperty = {
export const inputProperties = <R>(tool: Tool<R>): Array<InputProperty> => {
try {
const document = isEffectSchema(tool.input)
? (Schema.toJsonSchemaDocument(tool.input) as {
? (Schema.toJsonSchemaDocument(tool.input, { onExcessProperty: "error" }) as {
readonly schema: JsonSchema
readonly definitions?: Readonly<Record<string, JsonSchema>>
})
@@ -241,8 +245,7 @@ export const inputProperties = <R>(tool: Tool<R>): Array<InputProperty> => {
const definitions = document.definitions ?? {}
let schema = document.schema
if (schema.$ref !== undefined) {
const segment = schema.$ref.match(/^#\/(?:\$defs|definitions)\/([^/]+)$/)?.[1]
const name = segment === undefined ? undefined : JsonPointer.unescapeToken(segment)
const name = definitionName(schema.$ref)
const resolved = name === undefined ? undefined : definitions[name]
if (resolved === undefined) return []
schema = resolved
@@ -261,10 +264,16 @@ export const inputProperties = <R>(tool: Tool<R>): Array<InputProperty> => {
export const inputTypeScript = <R>(tool: Tool<R>, pretty = false): string =>
isEffectSchema(tool.input) ? toTypeScript(tool.input, false, pretty) : jsonSchemaToTypeScript(tool.input, pretty)
// Empty object schemas render as `{}` in compact form; anything with properties,
// an index signature, or union members renders differently, so equality is a
// conservative emptiness test for both Effect and JSON Schema inputs.
export const isEmptyInput = <R>(tool: Tool<R>): boolean => inputTypeScript(tool) === "{}"
// Effect 4.0 models an empty Struct as a non-nullish object, so inspect its AST.
// Raw JSON Schema inputs retain the compact `{}` rendering check.
export const isEmptyInput = <R>(tool: Tool<R>): boolean => {
if (!isEffectSchema(tool.input)) return inputTypeScript(tool) === "{}"
return (
SchemaAST.isObjects(tool.input.ast) &&
tool.input.ast.propertySignatures.length === 0 &&
tool.input.ast.indexSignatures.length === 0
)
}
export const outputTypeScript = <R>(tool: Tool<R>, pretty = false): string =>
tool.output === undefined
@@ -210,14 +210,11 @@ describe("Test262 JSON.stringify replacer adaptations", () => {
})
describe("CodeMode JSON callback boundaries", () => {
test("revivers and replacers see the holder as this", async () => {
expect(
await value(`
const revived = JSON.parse('{"a":{"b":1}}', function (key, item) { return key === "b" ? this.b + 1 : item })
const text = JSON.stringify({ a: 1, b: 2 }, function (key, item) { return key === "a" ? this.b : item })
return [revived, text]
`),
).toEqual([{ a: { b: 2 } }, '{"a":2,"b":2}'])
test("this remains unsupported rather than exposing callback holders", async () => {
const result = await Effect.runPromise(
CodeMode.execute({ code: `return JSON.parse("1", function (key, item) { return this })`, tools: {} }),
)
expect(result).toMatchObject({ ok: false, error: { kind: "UnsupportedSyntax" } })
})
test("prototype-named keys parse as own data and reach the reviver", async () => {
@@ -77,6 +77,8 @@ describe("new on a non-constructible callee", () => {
expect(failure.message).toStartWith(
"SyntaxError: Syntax 'ClassDeclaration' is not supported. This is a restricted JavaScript-like language. Supported: ",
)
expect(failure.message).toContain("Unsupported: classes, getters/setters, BigInt, and custom Symbols.")
expect(failure.message).toContain(
"Unsupported: classes, this, getters/setters, tagged templates, BigInt, and custom Symbols.",
)
})
})
+1 -188
View File
@@ -964,7 +964,7 @@ describe("coercion parity: unknown static members read as undefined", () => {
expect(await value(`return typeof Math.sum`)).toBe("undefined")
expect(await value(`return RegExp.quote === undefined`)).toBe(true)
expect(await value(`return Number.range === undefined`)).toBe(true)
expect(await value(`return String.dedent === undefined`)).toBe(true)
expect(await value(`return String.raw === undefined`)).toBe(true)
expect(await value(`return isFinite.something === undefined`)).toBe(true)
expect(await value(`return console.group === undefined`)).toBe(true)
expect(await value(`return Date.moment === undefined`)).toBe(true)
@@ -1079,190 +1079,3 @@ describe("functions are objects", () => {
).toEqual([3, ["count"], true, true, "fn", 3, true, true, null])
})
})
describe("tagged templates", () => {
test("the tag receives the cooked strings, their raw forms, and the substitutions in order", async () => {
expect(
await value(`
const tag = (strings, ...values) => [strings, strings.raw, values, Object.keys(strings)]
return tag\`a\${1}b\\n\${2}c\`
`),
).toEqual([
["a", "b\n", "c"],
["a", "b\\n", "c"],
[1, 2],
["0", "1", "2"],
])
})
test("an invalid escape cooks to undefined and keeps its raw text", async () => {
expect(await value(`return ((strings) => [strings[0] === undefined, strings.raw[0]])\`\\unicode\``)).toEqual([
true,
"\\unicode",
])
})
test("each site has one template object; different sites differ", async () => {
expect(
await value(`
const seen = []
const tag = (strings) => { seen.push(strings) }
for (let i = 0; i < 2; i++) tag\`x\${i}\`
tag\`x\${0}\`
return [seen[0] === seen[1], seen[0] === seen[2]]
`),
).toEqual([true, false])
})
test("the tag is read like a callee: members, chained tags, async tags, and the not-a-function error", async () => {
expect(
await value(`
const o = { tag: (strings) => strings[0].toUpperCase() }
const chain = () => chain
const asyncTag = async (strings, value) => strings[0] + value
let failure
try { (1)\`x\` } catch (error) { failure = error instanceof TypeError }
return [o.tag\`abc\`, typeof chain\`a\`\`b\`, await asyncTag\`n=\${1}\`, failure]
`),
).toEqual(["ABC", "function", "n=1", true])
})
test("raw is read-only", async () => {
expect(await value(`try { ((strings) => { strings.raw = 1 })\`a\` } catch (error) { return error.name }`)).toBe(
"TypeError",
)
})
})
describe("String.raw", () => {
test("joins the raw strings with the substitutions", async () => {
expect(await value(`return [String.raw\`a\\n\${1}b\`, String.raw({ raw: ["x", "y", "z"] }, 1, 2, 3)]`)).toEqual([
"a\\n1b",
"x1y2z",
])
})
test("extra substitutions are dropped, missing ones are skipped, and a program object's toString is used", async () => {
expect(
await value(`
const shout = { toString() { return "!" } }
return [String.raw({ raw: ["x", "y"] }, 1, 2), String.raw({ raw: ["x", "y", "z"] }, shout), String.raw({ raw: { length: 0 } })]
`),
).toEqual(["x1y", "x!yz", ""])
})
test("a template without a raw array is a TypeError", async () => {
const failure = await error(`String.raw(1)`)
expect(failure.message).toContain("String.raw expects a template object with a raw array")
})
})
describe("sloppy duplicate parameters and for...in targets", () => {
test("a repeated parameter name binds the last argument", async () => {
expect(await value(`function f(a, b, a) { return [a, b] } return [f(1, 2, 3), f(1)]`)).toEqual([
[3, 2],
[null, null],
])
})
test("for...in assigns to any target: members, computed members, and patterns", async () => {
expect(
await value(`
const x = {}, seen = [], a = []
let i = 0, first
for (x.y in { p: 1, q: 2 }) seen.push(x.y)
for (a[i++] in { p: 1, q: 2 });
for ([first] in { ab: 1 });
return [seen, x.y, a, first]
`),
).toEqual([["p", "q"], "q", ["p", "q"], "a"])
})
})
describe("this, arguments, and Function.prototype.call/apply/bind", () => {
test("this is the call receiver for non-arrow functions and lexical for arrows", async () => {
expect(
await value(`
const o = { n: 1, m() { return this.n }, a() { return (() => this.n)() }, bare() { return this } }
const detached = o.bare
function f() { return this }
return [o.m(), o["m"](), o?.m(), (o.m)(), o.a(), o.bare() === o, detached(), f(), (0, o.bare)(), this, (() => this)()]
`),
).toEqual([1, 1, 1, 1, 1, true, null, null, null, null, null])
})
test("this reaches generator and async methods and plain-function callbacks", async () => {
expect(
await value(`
const o = { n: 2, *g() { yield this.n }, async m() { return this.n }, xs: [1, 2], go() { return this.xs.map(function (x) { return [x, this] }) } }
return [[...o.g()], await o.m(), o.go()]
`),
).toEqual([
[2],
2,
[
[1, null],
[2, null],
],
])
})
test("arguments is an unmapped array-like that arrows and parameters interact with as in JS", async () => {
expect(
await value(`
function f(a) { arguments[0] = 9; return [arguments.length, arguments[1], a, [...arguments], Array.isArray(arguments), Object.prototype.toString.call(arguments), typeof arguments.map, (() => arguments[1])()] }
function shadow(arguments) { return arguments }
function hoisted() { var arguments; return arguments.length }
let outer
try { outer = arguments } catch (error) { outer = error.name }
return [f(1, 2), shadow(7), hoisted(1, 2, 3), outer]
`),
).toEqual([[2, 2, 1, [9, 2], false, "[object Arguments]", "undefined", 2], 7, 3, "ReferenceError"])
})
test("call, apply, and bind set this and arguments on program functions and built-ins", async () => {
expect(
await value(`
function f(a, b, c) { return [this, a, b, c] }
const g = f.bind({ k: 1 }, "A")
const arr = [1]
Array.prototype.push.call(arr, 2, 3)
return [
f.call("t", 1, 2),
f.apply({ k: 2 }, [1, 2]),
f.apply(null, { length: 2, 0: "x", 1: "y" }),
f.apply(null).length,
g("B", "C"), g.name, g.length,
f.bind(1).bind(2)()[0],
arr,
Math.max.apply(null, [1, 5, 3]),
Math.max.bind(null, 10)(3),
[1, 2].map(f.bind(null, 0)).map((r) => r[1]),
]
`),
).toEqual([
["t", 1, 2, null],
[{ k: 2 }, 1, 2, null],
[null, "x", "y", null],
4,
[{ k: 1 }, "A", "B", "C"],
"bound f",
2,
1,
[1, 2, 3],
5,
10,
[0, 0],
])
})
test("call and apply reject non-callable receivers and non-array-like argument lists", async () => {
expect((await error(`Function.prototype.call.call(1)`)).message).toContain(
"Function.prototype.call called on incompatible receiver",
)
expect((await error(`(() => 1).apply(null, 5)`)).message).toContain("expects an array-like argument list")
expect((await error(`function f(n) { return f.call(null, n + 1) } f(0)`)).message).toContain(
"Maximum call stack size exceeded",
)
})
})
+76 -5
View File
@@ -1,7 +1,13 @@
import { describe, expect, test } from "bun:test"
import { Effect, Schema } from "effect"
import { CodeMode, Tool } from "../src/index.js"
import { inputTypeScript, jsonSchemaToTypeScript, outputTypeScript } from "../src/tool-schema.js"
import {
decodeInput,
inputProperties,
inputTypeScript,
jsonSchemaToTypeScript,
outputTypeScript,
} from "../src/tool-schema.js"
// A raw JSON Schema tool in the shape an MCP adapter produces: render-only input schema
// whose property descriptions and constraints must surface as JSDoc in pretty signatures.
@@ -525,6 +531,34 @@ describe("pretty signature rendering", () => {
})
describe("JSON Schema definition scope", () => {
test.each(["Lookup Input", "café", "A/B~C% D#E"])(
"resolves Effect definition %s in signatures and input metadata",
(identifier) => {
const tool = Tool.make({
description: "Named tool",
input: Schema.Struct({ city: Schema.String }).annotate({ identifier }),
output: Schema.Struct({ city: Schema.String }).annotate({ identifier }),
execute: (input) => Effect.succeed(input),
})
expect(inputTypeScript(tool)).toBe("{ city: string }")
expect(outputTypeScript(tool)).toBe("{ city: string }")
expect(inputProperties(tool)).toEqual([{ name: "city", description: undefined, required: true }])
},
)
test.each(["#/$defs/%", "#/$defs/A~2B", "#/$defs/Missing", "#/$defs/Loop", "https://example.test/schema"])(
"keeps malformed, unresolved, and recursive reference %s unknown",
($ref) => {
const tool = Tool.make({
description: "Unresolved tool",
input: { $ref, $defs: { Loop: { $ref: "#/$defs/Loop" } } },
execute: () => Effect.succeed(null),
})
expect(inputTypeScript(tool)).toBe("unknown")
expect(inputProperties(tool)).toEqual([])
},
)
test.each(["definitions", "$defs"])("resolves root %s and lets $defs take precedence", (key) => {
const schema = { $ref: `#/${key}/Value`, [key]: { Value: { type: "string" } } }
expect(jsonSchemaToTypeScript(schema)).toBe("string")
@@ -612,14 +646,51 @@ describe("non-identifier property names render as quoted keys", () => {
input: Schema.Struct({ "foo-bar": Schema.String, plain: Schema.optionalKey(Schema.Number) }),
execute: () => Effect.succeed(null),
})
expect(inputTypeScript(tool)).toBe('{ "foo-bar": string; plain?: number | "Infinity" | "-Infinity" | "NaN" }')
expect(inputTypeScript(tool, true)).toBe(
["{", ' "foo-bar": string,', ' plain?: number | "Infinity" | "-Infinity" | "NaN",', "}"].join("\n"),
)
expect(inputTypeScript(tool)).toBe('{ "foo-bar": string; plain?: number }')
expect(inputTypeScript(tool, true)).toBe(["{", ' "foo-bar": string,', " plain?: number,", "}"].join("\n"))
})
})
describe("union schemas render every alternative", () => {
test("Effect numbers advertise the numeric values accepted by the input decoder", () => {
const tool = Tool.make({
description: "Numeric tool",
input: Schema.Struct({ amount: Schema.Number }),
output: Schema.Number,
execute: (input) => Effect.succeed(input.amount),
})
expect(inputTypeScript(tool)).toBe("{ amount: number }")
expect(inputTypeScript(tool, true)).toBe("{\n amount: number,\n}")
expect(outputTypeScript(tool)).toBe("number")
expect(outputTypeScript(tool, true)).toBe("number")
expect(decodeInput(tool, { amount: 42 })).toEqual({ amount: 42 })
for (const amount of ["NaN", "Infinity", "-Infinity"]) {
expect(() => decodeInput(tool, { amount })).toThrow("Expected number")
}
})
test("keeps unrelated and partial grouped string enums alongside numbers", () => {
expect(
jsonSchemaToTypeScript({
anyOf: [{ type: "number" }, { type: "string", enum: ["NaN", "Infinity", "unknown"] }],
}),
).toBe('number | "NaN" | "Infinity" | "unknown"')
expect(
jsonSchemaToTypeScript({
anyOf: [{ type: "number" }, { type: "string", enum: ["NaN", "Infinity"] }],
}),
).toBe('number | "NaN" | "Infinity"')
const tool = Tool.make({
description: "Number or status",
input: Schema.Union([Schema.Number, Schema.Literal("unknown")]),
output: Schema.Union([Schema.Number, Schema.Literal("unknown")]),
execute: (input) => Effect.succeed(input),
})
expect(inputTypeScript(tool)).toContain('"unknown"')
expect(outputTypeScript(tool)).toContain('"unknown"')
expect(decodeInput(tool, "unknown")).toBe("unknown")
})
test("anyOf with a number branch keeps sibling alternatives", () => {
const schema = {
anyOf: [{ type: "string" }, { type: "number" }],
+5 -9
View File
@@ -452,12 +452,10 @@ describe("RegExp", () => {
expect((await error(`return "aa".matchAll(/a/)`)).message).toContain("write /a/g, or use String.match")
})
test("any argument is a pattern string, as new RegExp(arg) reads it", async () => {
expect(
await value(
`return ["a42b".match(42)[0], "xnullx".search(null), "abc".match(undefined), [..."1a1".matchAll(1)].length]`,
),
).toEqual(["42", 1, [""], 2])
test("a non-pattern argument names the expected shapes", async () => {
const err = await error(`return "abc".match(42)`)
expect(err.message).toContain("expects a regular expression")
expect(err.message).toContain("not number")
})
test("source and flags properties read through", async () => {
@@ -1416,9 +1414,7 @@ describe("built-in iterators", () => {
const logged = await run(`console.log([1].keys()); return null`)
expect(logged.logs?.[0]).toBe("[opaque reference]")
expect((await error(`return [1].keys() + ""`)).message).toContain("Binary operators require data values")
expect((await error(`return [1].keys().next.call({})`)).message).toContain(
"Iterator.prototype.next called on incompatible receiver a data object",
)
expect((await error(`return [1].keys().next.call({})`)).message).toContain("is not a function")
expect((await error(`const it = [1].keys(); const next = it.next; return next()`)).message).toContain(
"Iterator.prototype.next called on incompatible receiver undefined",
)
+3 -3
View File
@@ -24,9 +24,9 @@ Without them the runner registers no tests, so CI is unaffected. Licensed under
`script/sync-test262.ts` skips a file when its frontmatter declares a `flags`, `features`, or `includes` value the
manifest marks unsupported, or when its code matches one of the manifest's `boundaries` patterns. The sync checks the
checkout is at the pinned revision, so every machine runs the same files. Boundaries are
intentional limits of the interpreter, not compatibility work: classes, prototype objects, property descriptors,
accessors, boxed primitives, sloppy mode, `eval`, `Symbol()`, and the `$262` host API. If one
checkout is at the pinned revision, so every machine runs the same 3993 files. Boundaries are
intentional limits of the interpreter, not compatibility work: classes, `this`, `arguments`, prototype objects,
property descriptors, accessors, boxed primitives, sloppy mode, `eval`, `Symbol()`, and the `$262` host API. If one
of those decisions changes, delete its entry and re-sync; the tests are upstream, not lost.
## Commands
+4 -12
View File
@@ -1,21 +1,13 @@
{
"revision": "250f204f23a9249ff204be2baec29600faae7b75",
"directories": [
"built-ins/Array/prototype",
"built-ins/Function/prototype/apply",
"built-ins/Function/prototype/bind",
"built-ins/Function/prototype/call",
"built-ins/Iterator",
"built-ins/String/raw",
"language/arguments-object",
"language/expressions/tagged-template",
"language/expressions/this",
"language/statements"
],
"directories": ["built-ins/Array/prototype", "language/statements", "built-ins/Iterator"],
"harness": ["assert.js", "sta.js", "compareArray.js", "doneprintHandle.js"],
"flags": ["module", "raw", "noStrict"],
"boundaries": {
"class": "\\bclass\\s*[A-Za-z_${]",
"this": "\\bthis\\b",
"arguments": "\\barguments\\b",
"call/apply/bind": "\\.(call|apply|bind)\\s*\\(",
"accessor properties": "\\b(get|set)\\s+[\\w$\\[][^\\n(]*\\(",
"property descriptors": "Object\\.(defineProperty|defineProperties|getOwnPropertyDescriptors?|getOwnPropertyNames|create|getPrototypeOf|setPrototypeOf|freeze|seal|preventExtensions|isFrozen|isSealed|isExtensible)\\b",
"boxed primitives": "\\bnew\\s+(String|Number|Boolean)\\s*\\(",
+1 -765
View File
@@ -4,92 +4,13 @@ built-ins/Array/prototype/concat/S15.4.4.4_A2_T2.js # Array.prototype.concat ca
built-ins/Array/prototype/concat/S15.4.4.4_A3_T1.js # arr.hasOwnProperty("1") must return true Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/concat/S15.4.4.4_A3_T2.js # b.hasOwnProperty("2") must return true Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/concat/S15.4.4.4_A3_T3.js # b.hasOwnProperty("2") must return true Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/concat/call-with-boolean.js # TypeError: Array.prototype.concat called on incompatible receiver a boolean.
built-ins/Array/prototype/concat/create-ctor-non-object.js # a.concat() throws a TypeError exception Expected a TypeError to be thrown but no exception was throw
built-ins/Array/prototype/copyWithin/call-with-boolean.js # TypeError: Array.prototype.copyWithin called on incompatible receiver a boolean.
built-ins/Array/prototype/copyWithin/coerced-values-start-change-target.js # Array.copyWithin expects start to be a number.
built-ins/Array/prototype/copyWithin/length-near-integer-limit.js # TypeError: Array.prototype.copyWithin called on incompatible receiver a data object.
built-ins/Array/prototype/copyWithin/return-abrupt-from-end.js # Expected a Test262Error but got a TypeError
built-ins/Array/prototype/copyWithin/return-abrupt-from-start.js # Expected a Test262Error but got a TypeError
built-ins/Array/prototype/copyWithin/return-abrupt-from-target.js # Expected a Test262Error but got a TypeError
built-ins/Array/prototype/copyWithin/return-this.js # TypeError: Array.prototype.copyWithin called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-1-10.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-1-11.js # TypeError: Array.prototype.every called on incompatible receiver a Date.
built-ins/Array/prototype/every/15.4.4.16-1-12.js # TypeError: Array.prototype.every called on incompatible receiver a RegExp.
built-ins/Array/prototype/every/15.4.4.16-1-13.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-1-14.js # TypeError: Array.prototype.every called on incompatible receiver an Error.
built-ins/Array/prototype/every/15.4.4.16-1-3.js # TypeError: Array.prototype.every called on incompatible receiver a boolean.
built-ins/Array/prototype/every/15.4.4.16-1-5.js # TypeError: Array.prototype.every called on incompatible receiver a number.
built-ins/Array/prototype/every/15.4.4.16-1-7.js # TypeError: Array.prototype.every called on incompatible receiver a string.
built-ins/Array/prototype/every/15.4.4.16-2-1.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-2-14.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-2-17.js # func(12, 11) !== true
built-ins/Array/prototype/every/15.4.4.16-2-19.js # TypeError: Array.prototype.every called on incompatible receiver a function.
built-ins/Array/prototype/every/15.4.4.16-2-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/every/15.4.4.16-2-6.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/every/15.4.4.16-3-1.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-10.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-11.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-12.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-13.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-14.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-15.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-16.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-17.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-18.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-19.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-2.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-20.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-21.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-22.js # toStringAccessed !== true
built-ins/Array/prototype/every/15.4.4.16-3-24.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-25.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-29.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-3.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-4.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-5.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-6.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-7.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-8.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-3-9.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-5-10.js # [11].every(callbackfn, objArray) !== true
built-ins/Array/prototype/every/15.4.4.16-5-14.js # [11].every(callbackfn, Math) !== true
built-ins/Array/prototype/every/15.4.4.16-5-15.js # [11].every(callbackfn, objDate) !== true
built-ins/Array/prototype/every/15.4.4.16-5-16.js # [11].every(callbackfn, objRegExp) !== true
built-ins/Array/prototype/every/15.4.4.16-5-17.js # [11].every(callbackfn, JSON) !== true
built-ins/Array/prototype/every/15.4.4.16-5-18.js # [11].every(callbackfn, objError) !== true
built-ins/Array/prototype/every/15.4.4.16-5-19.js # [11].every(callbackfn, arg) !== true
built-ins/Array/prototype/every/15.4.4.16-5-2.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/every/15.4.4.16-5-22.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/every/15.4.4.16-5-23.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/every/15.4.4.16-5-24.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/every/15.4.4.16-5-3.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/every/15.4.4.16-5-4.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/every/15.4.4.16-5-5.js # TypeError: foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/every/15.4.4.16-5-6.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/every/15.4.4.16-5-9.js # [11].every(callbackfn, objFunction) !== true
built-ins/Array/prototype/every/15.4.4.16-7-6.js # res Expected SameValue(«true», «false») to be true
built-ins/Array/prototype/every/15.4.4.16-7-8.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-i-1.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-i-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/every/15.4.4.16-7-c-i-7.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/every/15.4.4.16-7-c-i-8.js # [, , , ].every(callbackfn) Expected SameValue(«true», «false») to be true
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-16.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-17.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-18.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-19.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-20.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-21.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-22.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-23.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-6.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-7.js # Expected a Test262Error but got a TypeError
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-8.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-iii-1.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-iii-2.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-iii-27.js # [11].every(callbackfn) !== true
built-ins/Array/prototype/every/15.4.4.16-7-c-iii-3.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-7-c-iii-4.js # TypeError: Array.prototype.every called on incompatible receiver a data object.
built-ins/Array/prototype/every/15.4.4.16-8-10.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/every/15.4.4.16-8-2.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/every/15.4.4.16-8-3.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
@@ -98,66 +19,9 @@ built-ins/Array/prototype/every/15.4.4.16-8-5.js # … cannot be constructed: u
built-ins/Array/prototype/every/15.4.4.16-8-6.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/every/15.4.4.16-8-7.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/every/15.4.4.16-8-8.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/every/call-with-boolean.js # TypeError: Array.prototype.every called on incompatible receiver a boolean.
built-ins/Array/prototype/fill/call-with-boolean.js # TypeError: Array.prototype.fill called on incompatible receiver a boolean.
built-ins/Array/prototype/fill/length-near-integer-limit.js # TypeError: Array.prototype.fill called on incompatible receiver a data object.
built-ins/Array/prototype/fill/return-abrupt-from-end.js # Expected a Test262Error but got a TypeError
built-ins/Array/prototype/fill/return-abrupt-from-start.js # Expected a Test262Error but got a TypeError
built-ins/Array/prototype/fill/return-this.js # TypeError: Array.prototype.fill called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-1-10.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-1-11.js # TypeError: Array.prototype.filter called on incompatible receiver a Date.
built-ins/Array/prototype/filter/15.4.4.20-1-12.js # TypeError: Array.prototype.filter called on incompatible receiver a RegExp.
built-ins/Array/prototype/filter/15.4.4.20-1-13.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-1-14.js # TypeError: Array.prototype.filter called on incompatible receiver an Error.
built-ins/Array/prototype/filter/15.4.4.20-1-3.js # TypeError: Array.prototype.filter called on incompatible receiver a boolean.
built-ins/Array/prototype/filter/15.4.4.20-1-5.js # TypeError: Array.prototype.filter called on incompatible receiver a number.
built-ins/Array/prototype/filter/15.4.4.20-1-7.js # TypeError: Array.prototype.filter called on incompatible receiver a string.
built-ins/Array/prototype/filter/15.4.4.20-10-3.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/filter/15.4.4.20-2-1.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-2-14.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-2-19.js # TypeError: Array.prototype.filter called on incompatible receiver a function.
built-ins/Array/prototype/filter/15.4.4.20-2-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/filter/15.4.4.20-2-6.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/filter/15.4.4.20-3-1.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-10.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-11.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-12.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-13.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-14.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-15.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-16.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-17.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-18.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-19.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-2.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-20.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-21.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-22.js # firstStepOccured !== true
built-ins/Array/prototype/filter/15.4.4.20-3-23.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/filter/15.4.4.20-3-24.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-25.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-3.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-4.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-5.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-6.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-7.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-3-9.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-5-10.js # newArr[0] Expected SameValue(«undefined», «11») to be true
built-ins/Array/prototype/filter/15.4.4.20-5-14.js # newArr[0] Expected SameValue(«undefined», «11») to be true
built-ins/Array/prototype/filter/15.4.4.20-5-15.js # newArr[0] Expected SameValue(«undefined», «11») to be true
built-ins/Array/prototype/filter/15.4.4.20-5-16.js # newArr[0] Expected SameValue(«undefined», «11») to be true
built-ins/Array/prototype/filter/15.4.4.20-5-17.js # newArr[0] Expected SameValue(«undefined», «11») to be true
built-ins/Array/prototype/filter/15.4.4.20-5-18.js # newArr[0] Expected SameValue(«undefined», «11») to be true
built-ins/Array/prototype/filter/15.4.4.20-5-19.js # newArr[0] Expected SameValue(«undefined», «11») to be true
built-ins/Array/prototype/filter/15.4.4.20-5-2.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/filter/15.4.4.20-5-22.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/filter/15.4.4.20-5-23.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/filter/15.4.4.20-5-24.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/filter/15.4.4.20-5-3.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/filter/15.4.4.20-5-4.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/filter/15.4.4.20-5-5.js # TypeError: foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/filter/15.4.4.20-5-6.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/filter/15.4.4.20-5-9.js # newArr[0] Expected SameValue(«undefined», «11») to be true
built-ins/Array/prototype/filter/15.4.4.20-6-2.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/filter/15.4.4.20-6-3.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/filter/15.4.4.20-6-4.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
@@ -166,121 +30,11 @@ built-ins/Array/prototype/filter/15.4.4.20-6-6.js # … cannot be constructed:
built-ins/Array/prototype/filter/15.4.4.20-6-7.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/filter/15.4.4.20-6-8.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/filter/15.4.4.20-9-6.js # resArr.length Expected SameValue(«3», «4») to be true
built-ins/Array/prototype/filter/15.4.4.20-9-8.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-i-1.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-i-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/filter/15.4.4.20-9-c-i-7.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/filter/15.4.4.20-9-c-i-8.js # newArr.length Expected SameValue(«0», «1») to be true
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-16.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-17.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-18.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-19.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-20.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-21.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-22.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-23.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-6.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-7.js # Expected a Error but got a TypeError
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-8.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-iii-1-1.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-iii-1-2.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-iii-1-3.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-iii-1-4.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-iii-2.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-iii-28.js # newArr.length Expected SameValue(«0», «1») to be true
built-ins/Array/prototype/filter/15.4.4.20-9-c-iii-29.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-iii-3.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-iii-4.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/15.4.4.20-9-c-iii-5.js # TypeError: Array.prototype.filter called on incompatible receiver a data object.
built-ins/Array/prototype/filter/call-with-boolean.js # TypeError: Array.prototype.filter called on incompatible receiver a boolean.
built-ins/Array/prototype/filter/create-ctor-non-object.js # null value Expected a TypeError to be thrown but no exception was thrown at all
built-ins/Array/prototype/find/call-with-boolean.js # TypeError: Array.prototype.find called on incompatible receiver a boolean.
built-ins/Array/prototype/find/predicate-call-this-strict.js # Expected SameValue(«undefined», «object») to be true
built-ins/Array/prototype/findIndex/call-with-boolean.js # TypeError: Array.prototype.findIndex called on incompatible receiver a boolean.
built-ins/Array/prototype/findIndex/predicate-call-this-strict.js # Expected SameValue(«undefined», «object») to be true
built-ins/Array/prototype/findLast/call-with-boolean.js # TypeError: Array.prototype.findLast called on incompatible receiver a boolean.
built-ins/Array/prototype/findLast/maximum-index.js # TypeError: Array.prototype.findLast called on incompatible receiver a data object.
built-ins/Array/prototype/findLast/predicate-call-this-strict.js # Expected SameValue(«undefined», «object») to be true
built-ins/Array/prototype/findLastIndex/call-with-boolean.js # TypeError: Array.prototype.findLastIndex called on incompatible receiver a boolean.
built-ins/Array/prototype/findLastIndex/maximum-index.js # TypeError: Array.prototype.findLastIndex called on incompatible receiver a data object.
built-ins/Array/prototype/findLastIndex/predicate-call-this-strict.js # Expected SameValue(«undefined», «object») to be true
built-ins/Array/prototype/flat/array-like-objects.js # TypeError: Array.prototype.flat called on incompatible receiver a data object.
built-ins/Array/prototype/flat/call-with-boolean.js # TypeError: Array.prototype.flat called on incompatible receiver a boolean.
built-ins/Array/prototype/flat/non-object-ctor-throws.js # null value Expected a TypeError to be thrown but no exception was thrown at all
built-ins/Array/prototype/flat/proxy-access-count.js # ReferenceError: Unknown identifier '…'.
built-ins/Array/prototype/flatMap/call-with-boolean.js # TypeError: Array.prototype.flatMap called on incompatible receiver a boolean.
built-ins/Array/prototype/flatMap/proxy-access-count.js # ReferenceError: Unknown identifier '…'.
built-ins/Array/prototype/flatMap/thisArg-argument.js # Actual [undefined] and expected ["TestString"] should have the same contents. The value of actual is
built-ins/Array/prototype/forEach/15.4.4.18-1-10.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-1-11.js # TypeError: Array.prototype.forEach called on incompatible receiver a Date.
built-ins/Array/prototype/forEach/15.4.4.18-1-12.js # TypeError: Array.prototype.forEach called on incompatible receiver a RegExp.
built-ins/Array/prototype/forEach/15.4.4.18-1-13.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-1-14.js # TypeError: Array.prototype.forEach called on incompatible receiver an Error.
built-ins/Array/prototype/forEach/15.4.4.18-1-3.js # TypeError: Array.prototype.forEach called on incompatible receiver a boolean.
built-ins/Array/prototype/forEach/15.4.4.18-1-5.js # TypeError: Array.prototype.forEach called on incompatible receiver a number.
built-ins/Array/prototype/forEach/15.4.4.18-1-7.js # TypeError: Array.prototype.forEach called on incompatible receiver a string.
built-ins/Array/prototype/forEach/15.4.4.18-2-1.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-2-14.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-2-17.js # func(12, 11) !== true
built-ins/Array/prototype/forEach/15.4.4.18-2-19.js # TypeError: Array.prototype.forEach called on incompatible receiver a function.
built-ins/Array/prototype/forEach/15.4.4.18-2-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/forEach/15.4.4.18-2-6.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/forEach/15.4.4.18-3-1.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-10.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-11.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-12.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-13.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-14.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-15.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-16.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-17.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-18.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-19.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-2.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-20.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-21.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-23.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/forEach/15.4.4.18-3-24.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-25.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-3.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-4.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-5.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-6.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-7.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-3-9.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-5-10.js # result !== true
built-ins/Array/prototype/forEach/15.4.4.18-5-14.js # result !== true
built-ins/Array/prototype/forEach/15.4.4.18-5-15.js # result !== true
built-ins/Array/prototype/forEach/15.4.4.18-5-16.js # result !== true
built-ins/Array/prototype/forEach/15.4.4.18-5-17.js # result !== true
built-ins/Array/prototype/forEach/15.4.4.18-5-18.js # result !== true
built-ins/Array/prototype/forEach/15.4.4.18-5-19.js # result !== true
built-ins/Array/prototype/forEach/15.4.4.18-5-2.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/forEach/15.4.4.18-5-22.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/forEach/15.4.4.18-5-23.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/forEach/15.4.4.18-5-24.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/forEach/15.4.4.18-5-3.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/forEach/15.4.4.18-5-4.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/forEach/15.4.4.18-5-5.js # TypeError: foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/forEach/15.4.4.18-5-6.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/forEach/15.4.4.18-5-9.js # result !== true
built-ins/Array/prototype/forEach/15.4.4.18-7-5.js # callCnt Expected SameValue(«4», «5») to be true
built-ins/Array/prototype/forEach/15.4.4.18-7-8.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-i-1.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-i-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/forEach/15.4.4.18-7-c-i-7.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/forEach/15.4.4.18-7-c-i-8.js # testResult !== true
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-16.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-17.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-18.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-19.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-20.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-21.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-22.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-23.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-6.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-7.js # Expected a Error but got a TypeError
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-8.js # TypeError: Array.prototype.forEach called on incompatible receiver a data object.
built-ins/Array/prototype/forEach/15.4.4.18-8-10.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/forEach/15.4.4.18-8-2.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/forEach/15.4.4.18-8-3.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
@@ -290,135 +44,21 @@ built-ins/Array/prototype/forEach/15.4.4.18-8-6.js # … cannot be constructed:
built-ins/Array/prototype/forEach/15.4.4.18-8-7.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/forEach/15.4.4.18-8-8.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/forEach/15.4.4.18-8-9.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/forEach/call-with-boolean.js # TypeError: Array.prototype.forEach called on incompatible receiver a boolean.
built-ins/Array/prototype/includes/call-with-boolean.js # TypeError: Array.prototype.includes called on incompatible receiver a boolean.
built-ins/Array/prototype/includes/length-boundaries.js # TypeError: Array.prototype.includes called on incompatible receiver a data object.
built-ins/Array/prototype/includes/return-abrupt-tointeger-fromindex.js # Expected a Test262Error but got a TypeError
built-ins/Array/prototype/includes/return-abrupt-tonumber-length.js # valueOf Expected a Test262Error but got a TypeError
built-ins/Array/prototype/includes/tointeger-fromindex.js # Array.includes expects start index to be a number.
built-ins/Array/prototype/includes/tolength-length.js # TypeError: Array.prototype.includes called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-1-10.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-1-11.js # TypeError: Array.prototype.indexOf called on incompatible receiver a Date.
built-ins/Array/prototype/indexOf/15.4.4.14-1-12.js # TypeError: Array.prototype.indexOf called on incompatible receiver a RegExp.
built-ins/Array/prototype/indexOf/15.4.4.14-1-13.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-1-14.js # TypeError: Array.prototype.indexOf called on incompatible receiver an Error.
built-ins/Array/prototype/indexOf/15.4.4.14-1-3.js # TypeError: Array.prototype.indexOf called on incompatible receiver a boolean.
built-ins/Array/prototype/indexOf/15.4.4.14-1-5.js # TypeError: Array.prototype.indexOf called on incompatible receiver a number.
built-ins/Array/prototype/indexOf/15.4.4.14-1-7.js # TypeError: Array.prototype.indexOf called on incompatible receiver a string.
built-ins/Array/prototype/indexOf/15.4.4.14-1-9.js # TypeError: Array.prototype.indexOf called on incompatible receiver a function.
built-ins/Array/prototype/indexOf/15.4.4.14-2-1.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-2-14.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-2-17.js # func(0, true) !== true
built-ins/Array/prototype/indexOf/15.4.4.14-2-19.js # TypeError: Array.prototype.indexOf called on incompatible receiver a function.
built-ins/Array/prototype/indexOf/15.4.4.14-2-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/indexOf/15.4.4.14-2-6.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/indexOf/15.4.4.14-3-1.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-10.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-11.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-12.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-13.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-14.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-15.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-16.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-17.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-18.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-19.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-2.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-20.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-21.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-22.js # toStringAccessed
built-ins/Array/prototype/indexOf/15.4.4.14-3-23.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/indexOf/15.4.4.14-3-24.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-25.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-28.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-29.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-3.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-4.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-5.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-6.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-7.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-8.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-3-9.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-4-10.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-4-11.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-4-2.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-4-3.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-4-4.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-4-5.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-4-6.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-4-7.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-4-8.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-4-9.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-5-23.js # Array.indexOf expects start index to be a number.
built-ins/Array/prototype/indexOf/15.4.4.14-5-24.js # toStringAccessed
built-ins/Array/prototype/indexOf/15.4.4.14-5-25.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/indexOf/15.4.4.14-9-7.js # Array assignment result contains a circular value.
built-ins/Array/prototype/indexOf/15.4.4.14-9-a-2.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-9-a-3.js # Array.indexOf expects start index to be a number.
built-ins/Array/prototype/indexOf/15.4.4.14-9-a-5.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-9-a-6.js # Array.indexOf expects start index to be a number.
built-ins/Array/prototype/indexOf/15.4.4.14-9-b-i-1.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-9-b-i-4.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/15.4.4.14-9-b-i-7.js # [, , , ].indexOf(true) Expected SameValue(«-1», «0») to be true
built-ins/Array/prototype/indexOf/15.4.4.14-9-b-i-8.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/indexOf/call-with-boolean.js # TypeError: Array.prototype.indexOf called on incompatible receiver a boolean.
built-ins/Array/prototype/indexOf/length-near-integer-limit.js # TypeError: Array.prototype.indexOf called on incompatible receiver a data object.
built-ins/Array/prototype/join/S15.4.4.5_A2_T1.js # Array.prototype.join called on incompatible receiver a data object.
built-ins/Array/prototype/join/S15.4.4.5_A2_T4.js # Array.prototype.join called on incompatible receiver a data object.
built-ins/Array/prototype/join/S15.4.4.5_A3.1_T2.js # Array.join expects zero arguments or one string separator.
built-ins/Array/prototype/join/S15.4.4.5_A3.2_T2.js # x.join() must return "*" Expected SameValue(«"[object Object]"», «"*"») to be true
built-ins/Array/prototype/join/S15.4.4.5_A4_T3.js # Array.prototype.join called on incompatible receiver a data object.
built-ins/Array/prototype/join/S15.4.4.5_A5_T1.js # #1: Array.prototype[1] = 1; x = [0]; x.length = 2; x.join() === "0,1". Actual: 0,
built-ins/Array/prototype/join/call-with-boolean.js # TypeError: Array.prototype.join called on incompatible receiver a boolean.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-1-10.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-1-11.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a Date.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-1-12.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a RegExp.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-1-13.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-1-14.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver an Error.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-1-3.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a boolean.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-1-5.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a number.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-1-7.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a string.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-1-9.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a function.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-2-1.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-2-14.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-2-17.js # func(0, targetObj) !== true
built-ins/Array/prototype/lastIndexOf/15.4.4.15-2-19.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a function.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-2-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/lastIndexOf/15.4.4.15-2-6.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-1.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-10.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-11.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-12.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-13.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-14.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-15.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-16.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-17.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-19.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-2.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-20.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-21.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-22.js # toStringAccessed
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-23.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-24.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-25.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-28.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-3.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-4.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-5.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-6.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-7.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-9.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-4-10.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-4-11.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-4-2.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-4-3.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-4-4.js # TypeError: foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/lastIndexOf/15.4.4.15-4-5.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-4-6.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-4-7.js # TypeError: foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/lastIndexOf/15.4.4.15-4-8.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-4-9.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-21.js # Array.lastIndexOf expects start index to be a number.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-22.js # Array.lastIndexOf expects start index to be a number.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-23.js # Array.lastIndexOf expects start index to be a number.
@@ -426,103 +66,12 @@ built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-24.js # toStringAccessed
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-25.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-4.js # a.lastIndexOf(2,undefined) Expected SameValue(«1», «-1») to be true
built-ins/Array/prototype/lastIndexOf/15.4.4.15-8-7.js # Array assignment result contains a circular value.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-8-a-2.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-8-a-3.js # Array.lastIndexOf expects start index to be a number.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-8-a-5.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-8-b-i-1.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-8-b-i-4.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/15.4.4.15-8-b-i-7.js # [, , , ].lastIndexOf(true) Expected SameValue(«-1», «0») to be true
built-ins/Array/prototype/lastIndexOf/15.4.4.15-8-b-i-8.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/lastIndexOf/call-with-boolean.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a boolean.
built-ins/Array/prototype/lastIndexOf/length-near-integer-limit.js # TypeError: Array.prototype.lastIndexOf called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-1-10.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-1-11.js # TypeError: Array.prototype.map called on incompatible receiver a Date.
built-ins/Array/prototype/map/15.4.4.19-1-12.js # TypeError: Array.prototype.map called on incompatible receiver a RegExp.
built-ins/Array/prototype/map/15.4.4.19-1-13.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-1-14.js # TypeError: Array.prototype.map called on incompatible receiver an Error.
built-ins/Array/prototype/map/15.4.4.19-1-3.js # TypeError: Array.prototype.map called on incompatible receiver a boolean.
built-ins/Array/prototype/map/15.4.4.19-1-5.js # TypeError: Array.prototype.map called on incompatible receiver a number.
built-ins/Array/prototype/map/15.4.4.19-1-7.js # TypeError: Array.prototype.map called on incompatible receiver a string.
built-ins/Array/prototype/map/15.4.4.19-2-1.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-2-14.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-2-19.js # TypeError: Array.prototype.map called on incompatible receiver a function.
built-ins/Array/prototype/map/15.4.4.19-2-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-2-6.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-3-1.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-10.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-11.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-12.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-13.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-14.js # Expected a RangeError but got a TypeError
built-ins/Array/prototype/map/15.4.4.19-3-15.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-16.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-17.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-18.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-19.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-2.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-20.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-21.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-23.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-3-24.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-25.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-28.js # Expected a RangeError but got a TypeError
built-ins/Array/prototype/map/15.4.4.19-3-29.js # Expected a RangeError but got a TypeError
built-ins/Array/prototype/map/15.4.4.19-3-3.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-4.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-5.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-6.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-7.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-3-8.js # Expected a RangeError but got a TypeError
built-ins/Array/prototype/map/15.4.4.19-3-9.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-5-10.js # testResult[0] Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/map/15.4.4.19-5-14.js # testResult[0] Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/map/15.4.4.19-5-15.js # testResult[0] Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/map/15.4.4.19-5-16.js # testResult[0] Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/map/15.4.4.19-5-17.js # testResult[0] Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/map/15.4.4.19-5-18.js # testResult[0] Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/map/15.4.4.19-5-19.js # testResult[0] Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/map/15.4.4.19-5-2.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/map/15.4.4.19-5-22.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/map/15.4.4.19-5-23.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/map/15.4.4.19-5-24.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/map/15.4.4.19-5-3.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/map/15.4.4.19-5-4.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/map/15.4.4.19-5-5.js # TypeError: foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-5-6.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/map/15.4.4.19-5-9.js # testResult[0] Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/map/15.4.4.19-8-6.js # resArr[4] Expected SameValue(«undefined», «1») to be true
built-ins/Array/prototype/map/15.4.4.19-8-8.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-i-1.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-i-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-8-c-i-7.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-8-c-i-8.js # newArr[1] Expected SameValue(«13», «true») to be true
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-16.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-17.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-18.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-19.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-20.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-21.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-22.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-23.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-6.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-7.js # Expected a Error but got a TypeError
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-8.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-iii-2.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-iii-3.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-iii-4.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-8-c-iii-5.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-9-10.js # TypeError: Foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-9-11.js # TypeError: Foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-9-12.js # TypeError: Foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-9-3.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/map/15.4.4.19-9-5.js # TypeError: Array.prototype.map called on incompatible receiver a data object.
built-ins/Array/prototype/map/15.4.4.19-9-6.js # TypeError: Foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-9-7.js # TypeError: Foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-9-8.js # TypeError: Foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/15.4.4.19-9-9.js # TypeError: Foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/map/call-with-boolean.js # TypeError: Array.prototype.map called on incompatible receiver a boolean.
built-ins/Array/prototype/map/create-ctor-non-object.js # null value Expected a TypeError to be thrown but no exception was thrown at all
built-ins/Array/prototype/map/create-non-array-invalid-len.js # Expected a RangeError but got a TypeError
built-ins/Array/prototype/pop/S15.4.4.6_A2_T1.js # Array.prototype.pop called on incompatible receiver a data object.
built-ins/Array/prototype/pop/S15.4.4.6_A2_T4.js # Array.prototype.pop called on incompatible receiver a data object.
built-ins/Array/prototype/pop/S15.4.4.6_A3_T1.js # Array.prototype.pop called on incompatible receiver a data object.
@@ -530,9 +79,6 @@ built-ins/Array/prototype/pop/S15.4.4.6_A3_T2.js # Array.prototype.pop called o
built-ins/Array/prototype/pop/S15.4.4.6_A3_T3.js # Array.prototype.pop called on incompatible receiver a data object.
built-ins/Array/prototype/pop/S15.4.4.6_A4_T1.js # #1: Array.prototype[1] = 1; x = [0]; x.length = 2; x.pop() === 1. Actual: undefined
built-ins/Array/prototype/pop/S15.4.4.6_A4_T2.js # Array.prototype.pop called on incompatible receiver a data object.
built-ins/Array/prototype/pop/call-with-boolean.js # TypeError: Array.prototype.pop called on incompatible receiver a boolean.
built-ins/Array/prototype/pop/clamps-to-integer-limit.js # TypeError: Array.prototype.pop called on incompatible receiver a data object.
built-ins/Array/prototype/pop/length-near-integer-limit.js # TypeError: Array.prototype.pop called on incompatible receiver a data object.
built-ins/Array/prototype/push/S15.4.4.7_A2_T1.js # Array.prototype.push called on incompatible receiver a data object.
built-ins/Array/prototype/push/S15.4.4.7_A2_T3.js # Array.prototype.push called on incompatible receiver a data object.
built-ins/Array/prototype/push/S15.4.4.7_A3.js # The value of x[4294967295] is expected to be "x" Expected SameValue(«undefined», «"x"») to be true
@@ -540,51 +86,10 @@ built-ins/Array/prototype/push/S15.4.4.7_A4_T1.js # Array.prototype.push called
built-ins/Array/prototype/push/S15.4.4.7_A4_T2.js # Array.prototype.push called on incompatible receiver a data object.
built-ins/Array/prototype/push/S15.4.4.7_A4_T3.js # Array.prototype.push called on incompatible receiver a data object.
built-ins/Array/prototype/push/S15.4.4.7_A5_T1.js # Array.prototype.push called on incompatible receiver a data object.
built-ins/Array/prototype/push/call-with-boolean.js # TypeError: Array.prototype.push called on incompatible receiver a boolean.
built-ins/Array/prototype/push/clamps-to-integer-limit.js # TypeError: Array.prototype.push called on incompatible receiver a data object.
built-ins/Array/prototype/push/length-near-integer-limit.js # TypeError: Array.prototype.push called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-1-10.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-1-11.js # TypeError: Array.prototype.reduce called on incompatible receiver a Date.
built-ins/Array/prototype/reduce/15.4.4.21-1-12.js # TypeError: Array.prototype.reduce called on incompatible receiver a RegExp.
built-ins/Array/prototype/reduce/15.4.4.21-1-13.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-1-14.js # TypeError: Array.prototype.reduce called on incompatible receiver an Error.
built-ins/Array/prototype/reduce/15.4.4.21-1-3.js # TypeError: Array.prototype.reduce called on incompatible receiver a boolean.
built-ins/Array/prototype/reduce/15.4.4.21-1-5.js # TypeError: Array.prototype.reduce called on incompatible receiver a number.
built-ins/Array/prototype/reduce/15.4.4.21-1-7.js # TypeError: Array.prototype.reduce called on incompatible receiver a string.
built-ins/Array/prototype/reduce/15.4.4.21-10-3.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduce/15.4.4.21-10-4.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduce/15.4.4.21-10-6.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduce/15.4.4.21-10-7.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduce/15.4.4.21-2-1.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-2-14.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-2-17.js # func(12, 11) Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/reduce/15.4.4.21-2-19.js # TypeError: Array.prototype.reduce called on incompatible receiver a function.
built-ins/Array/prototype/reduce/15.4.4.21-2-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduce/15.4.4.21-2-6.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduce/15.4.4.21-3-1.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-10.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-11.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-12.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-13.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-14.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-15.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-16.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-17.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-18.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-19.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-2.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-20.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-21.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-22.js # toStringAccessed !== true
built-ins/Array/prototype/reduce/15.4.4.21-3-23.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduce/15.4.4.21-3-24.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-25.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-3.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-4.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-5.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-6.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-7.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-3-9.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-5-2.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduce/15.4.4.21-5-3.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduce/15.4.4.21-5-4.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
@@ -600,77 +105,14 @@ built-ins/Array/prototype/reduce/15.4.4.21-7-6.js # … cannot be constructed:
built-ins/Array/prototype/reduce/15.4.4.21-7-7.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduce/15.4.4.21-7-8.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduce/15.4.4.21-7-9.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduce/15.4.4.21-8-b-iii-1-1.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-8-b-iii-1-29.js # TypeError: Array.prototype.reduce called on incompatible receiver a function.
built-ins/Array/prototype/reduce/15.4.4.21-8-b-iii-1-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduce/15.4.4.21-8-b-iii-1-7.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduce/15.4.4.21-8-b-iii-1-8.js # Array.reduce of an empty array with no initial value.
built-ins/Array/prototype/reduce/15.4.4.21-8-c-4.js # Array.reduce of an empty array with no initial value.
built-ins/Array/prototype/reduce/15.4.4.21-9-6.js # res Expected SameValue(«"123"», «"1235"») to be true
built-ins/Array/prototype/reduce/15.4.4.21-9-c-i-1.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-i-29.js # TypeError: Array.prototype.reduce called on incompatible receiver a function.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-i-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduce/15.4.4.21-9-c-i-7.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduce/15.4.4.21-9-c-i-8.js # testResult !== true
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-16.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-18.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-20.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-21.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-22.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-23.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-24.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-25.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-26.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-30.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-31.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-32.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-33.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-34.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-35.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-37.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-7.js # Expected a Error but got a TypeError
built-ins/Array/prototype/reduce/15.4.4.21-9-c-ii-8.js # TypeError: Array.prototype.reduce called on incompatible receiver a data object.
built-ins/Array/prototype/reduce/call-with-boolean.js # TypeError: Array.prototype.reduce called on incompatible receiver a boolean.
built-ins/Array/prototype/reduceRight/15.4.4.22-1-10.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-1-11.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a Date.
built-ins/Array/prototype/reduceRight/15.4.4.22-1-12.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a RegExp.
built-ins/Array/prototype/reduceRight/15.4.4.22-1-13.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-1-14.js # TypeError: Array.prototype.reduceRight called on incompatible receiver an Error.
built-ins/Array/prototype/reduceRight/15.4.4.22-1-3.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a boolean.
built-ins/Array/prototype/reduceRight/15.4.4.22-1-5.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a number.
built-ins/Array/prototype/reduceRight/15.4.4.22-1-7.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a string.
built-ins/Array/prototype/reduceRight/15.4.4.22-10-3.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduceRight/15.4.4.22-10-4.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduceRight/15.4.4.22-10-6.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduceRight/15.4.4.22-10-7.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduceRight/15.4.4.22-2-1.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-2-14.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-2-19.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a function.
built-ins/Array/prototype/reduceRight/15.4.4.22-2-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduceRight/15.4.4.22-2-6.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduceRight/15.4.4.22-3-1.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-10.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-11.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-12.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-13.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-14.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-15.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-16.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-17.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-18.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-19.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-2.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-20.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-21.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-22.js # toStringAccessed !== true
built-ins/Array/prototype/reduceRight/15.4.4.22-3-24.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-25.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-3.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-4.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-5.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-6.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-7.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-3-9.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-5-2.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduceRight/15.4.4.22-5-3.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduceRight/15.4.4.22-5-4.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
@@ -686,50 +128,20 @@ built-ins/Array/prototype/reduceRight/15.4.4.22-7-6.js # … cannot be construc
built-ins/Array/prototype/reduceRight/15.4.4.22-7-7.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduceRight/15.4.4.22-7-8.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduceRight/15.4.4.22-7-9.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/reduceRight/15.4.4.22-8-b-iii-1-1.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-8-b-iii-1-29.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a function.
built-ins/Array/prototype/reduceRight/15.4.4.22-8-b-iii-1-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduceRight/15.4.4.22-8-b-iii-1-7.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduceRight/15.4.4.22-8-b-iii-1-8.js # Array.reduceRight of an empty array with no initial value.
built-ins/Array/prototype/reduceRight/15.4.4.22-8-c-4.js # Array.reduceRight of an empty array with no initial value.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-6.js # res Expected SameValue(«"91"», «"151"») to be true
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-i-1.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-i-29.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a function.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-i-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-i-7.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-i-8.js # testResult !== true
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-16.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-20.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-21.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-22.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-23.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-24.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-25.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-26.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-30.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-31.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-32.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-33.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-34.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-35.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-37.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-7.js # Expected a Test262Error but got a TypeError
built-ins/Array/prototype/reduceRight/15.4.4.22-9-c-ii-8.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a data object.
built-ins/Array/prototype/reduceRight/call-with-boolean.js # TypeError: Array.prototype.reduceRight called on incompatible receiver a boolean.
built-ins/Array/prototype/reduceRight/length-near-integer-limit.js # The value of acc.length is expected to be 2 Expected SameValue(«undefined», «2») to be true
built-ins/Array/prototype/reverse/S15.4.4.8_A2_T1.js # Array.prototype.reverse called on incompatible receiver a data object.
built-ins/Array/prototype/reverse/S15.4.4.8_A3_T3.js # Array.prototype.reverse called on incompatible receiver a data object.
built-ins/Array/prototype/reverse/S15.4.4.8_A4_T1.js # #1: Array.prototype[1] = 1; x = [0]; x.length = 2; x.reverse(); x[0] === 1. Actual: undefined
built-ins/Array/prototype/reverse/S15.4.4.8_A4_T2.js # Array.prototype.reverse called on incompatible receiver a data object.
built-ins/Array/prototype/reverse/call-with-boolean.js # TypeError: Array.prototype.reverse called on incompatible receiver a boolean.
built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-object.js # TypeError: Only init object properties are supported.
built-ins/Array/prototype/shift/S15.4.4.9_A2_T1.js # Array.prototype.shift called on incompatible receiver a data object.
built-ins/Array/prototype/shift/S15.4.4.9_A2_T4.js # Array.prototype.shift called on incompatible receiver a data object.
built-ins/Array/prototype/shift/S15.4.4.9_A2_T5.js # Array.prototype.shift called on incompatible receiver a data object.
built-ins/Array/prototype/shift/S15.4.4.9_A3_T3.js # Array.prototype.shift called on incompatible receiver a data object.
built-ins/Array/prototype/shift/S15.4.4.9_A4_T1.js # #2: Array.prototype[1] = 1; x = [0]; x.length = 2; x.shift(); x[0] === 1. Actual: undefined
built-ins/Array/prototype/shift/S15.4.4.9_A4_T2.js # Array.prototype.shift called on incompatible receiver a data object.
built-ins/Array/prototype/shift/call-with-boolean.js # TypeError: Array.prototype.shift called on incompatible receiver a boolean.
built-ins/Array/prototype/slice/S15.4.4.10_A2.2_T5.js # Array.slice expects end to be a number.
built-ins/Array/prototype/slice/S15.4.4.10_A2_T1.js # Array.prototype.slice called on incompatible receiver a data object.
built-ins/Array/prototype/slice/S15.4.4.10_A2_T2.js # Array.prototype.slice called on incompatible receiver a data object.
@@ -741,89 +153,9 @@ built-ins/Array/prototype/slice/S15.4.4.10_A3_T1.js # Expected a RangeError but
built-ins/Array/prototype/slice/S15.4.4.10_A3_T2.js # Expected a RangeError but got a TypeError
built-ins/Array/prototype/slice/S15.4.4.10_A3_T3.js # Array.prototype.slice called on incompatible receiver a data object.
built-ins/Array/prototype/slice/S15.4.4.10_A4_T1.js # #3: Array.prototype[1] = 1; x = [0]; x.length = 2; var arr = x.slice(); arr.hasOwnProperty('…') ===
built-ins/Array/prototype/slice/call-with-boolean.js # TypeError: Array.prototype.slice called on incompatible receiver a boolean.
built-ins/Array/prototype/slice/create-ctor-non-object.js # null value Expected a TypeError to be thrown but no exception was thrown at all
built-ins/Array/prototype/slice/length-exceeding-integer-limit-proxied-array.js # ReferenceError: Unknown identifier '…'.
built-ins/Array/prototype/slice/length-exceeding-integer-limit.js # TypeError: Array.prototype.slice called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-1-10.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-1-11.js # TypeError: Array.prototype.some called on incompatible receiver a Date.
built-ins/Array/prototype/some/15.4.4.17-1-12.js # TypeError: Array.prototype.some called on incompatible receiver a RegExp.
built-ins/Array/prototype/some/15.4.4.17-1-13.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-1-14.js # TypeError: Array.prototype.some called on incompatible receiver an Error.
built-ins/Array/prototype/some/15.4.4.17-1-3.js # TypeError: Array.prototype.some called on incompatible receiver a boolean.
built-ins/Array/prototype/some/15.4.4.17-1-5.js # TypeError: Array.prototype.some called on incompatible receiver a number.
built-ins/Array/prototype/some/15.4.4.17-1-7.js # TypeError: Array.prototype.some called on incompatible receiver a string.
built-ins/Array/prototype/some/15.4.4.17-2-1.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-2-14.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-2-17.js # func(9, 11) !== true
built-ins/Array/prototype/some/15.4.4.17-2-19.js # TypeError: Array.prototype.some called on incompatible receiver a function.
built-ins/Array/prototype/some/15.4.4.17-2-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/some/15.4.4.17-2-6.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/some/15.4.4.17-3-1.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-10.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-11.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-12.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-13.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-14.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-15.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-16.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-17.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-18.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-19.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-2.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-20.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-21.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-22.js # toStringAccessed !== true
built-ins/Array/prototype/some/15.4.4.17-3-23.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/some/15.4.4.17-3-24.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-25.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-28.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-29.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-3.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-4.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-5.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-6.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-7.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-8.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-3-9.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-5-10.js # [11].some(callbackfn, objArray) !== true
built-ins/Array/prototype/some/15.4.4.17-5-14.js # [11].some(callbackfn, Math) !== true
built-ins/Array/prototype/some/15.4.4.17-5-15.js # [11].some(callbackfn, objDate) !== true
built-ins/Array/prototype/some/15.4.4.17-5-16.js # [11].some(callbackfn, objRegExp) !== true
built-ins/Array/prototype/some/15.4.4.17-5-17.js # [11].some(callbackfn, JSON) !== true
built-ins/Array/prototype/some/15.4.4.17-5-18.js # [11].some(callbackfn, objError) !== true
built-ins/Array/prototype/some/15.4.4.17-5-19.js # [11].some(callbackfn, arg) !== true
built-ins/Array/prototype/some/15.4.4.17-5-2.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/some/15.4.4.17-5-22.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/some/15.4.4.17-5-23.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/some/15.4.4.17-5-24.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/some/15.4.4.17-5-3.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/some/15.4.4.17-5-4.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/some/15.4.4.17-5-5.js # TypeError: foo cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/some/15.4.4.17-5-6.js # TypeError: Cannot read properties of undefined (reading '…').
built-ins/Array/prototype/some/15.4.4.17-5-9.js # [11].some(callbackfn, objFunction) !== true
built-ins/Array/prototype/some/15.4.4.17-7-6.js # res Expected SameValue(«false», «true») to be true
built-ins/Array/prototype/some/15.4.4.17-7-8.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-i-1.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-i-3.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/some/15.4.4.17-7-c-i-7.js # TypeError: Con cannot be constructed: user-defined constructors and classes are not supported. Call
built-ins/Array/prototype/some/15.4.4.17-7-c-i-8.js # [, ].some(callbackfn) !== true
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-16.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-17.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-18.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-19.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-20.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-21.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-22.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-23.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-6.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-7.js # Expected a Error but got a TypeError
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-8.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-iii-1.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-iii-2.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-iii-26.js # [11].some(callbackfn) !== true
built-ins/Array/prototype/some/15.4.4.17-7-c-iii-3.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-7-c-iii-4.js # TypeError: Array.prototype.some called on incompatible receiver a data object.
built-ins/Array/prototype/some/15.4.4.17-8-10.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/some/15.4.4.17-8-2.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/some/15.4.4.17-8-3.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
@@ -832,7 +164,6 @@ built-ins/Array/prototype/some/15.4.4.17-8-5.js # … cannot be constructed: us
built-ins/Array/prototype/some/15.4.4.17-8-6.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/some/15.4.4.17-8-7.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/some/15.4.4.17-8-8.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
built-ins/Array/prototype/some/call-with-boolean.js # TypeError: Array.prototype.some called on incompatible receiver a boolean.
built-ins/Array/prototype/sort/S15.4.4.11_A2.1_T3.js # #1: Check ToString operator
built-ins/Array/prototype/sort/S15.4.4.11_A2.2_T3.js # #1: Check ToString operator
built-ins/Array/prototype/sort/S15.4.4.11_A3_T1.js # Array.prototype.sort called on incompatible receiver a data object.
@@ -851,76 +182,27 @@ built-ins/Array/prototype/splice/S15.4.4.12_A3_T3.js # Array.prototype.splice c
built-ins/Array/prototype/splice/S15.4.4.12_A4_T1.js # Array.prototype.splice called on incompatible receiver a data object.
built-ins/Array/prototype/splice/S15.4.4.12_A4_T2.js # Array.prototype.splice called on incompatible receiver a data object.
built-ins/Array/prototype/splice/S15.4.4.12_A4_T3.js # Array.prototype.splice called on incompatible receiver a data object.
built-ins/Array/prototype/splice/call-with-boolean.js # TypeError: Array.prototype.splice called on incompatible receiver a boolean.
built-ins/Array/prototype/splice/clamps-length-to-integer-limit.js # TypeError: Array.prototype.splice called on incompatible receiver a data object.
built-ins/Array/prototype/splice/create-ctor-non-object.js # null value Expected a TypeError to be thrown but no exception was thrown at all
built-ins/Array/prototype/splice/length-and-deleteCount-exceeding-integer-limit.js # TypeError: Array.prototype.splice called on incompatible receiver a data object.
built-ins/Array/prototype/splice/length-exceeding-integer-limit-shrink-array.js # TypeError: Array.prototype.splice called on incompatible receiver a data object.
built-ins/Array/prototype/splice/length-near-integer-limit-grow-array.js # TypeError: Array.prototype.splice called on incompatible receiver a data object.
built-ins/Array/prototype/toLocaleString/S15.4.4.3_A3_T1.js # #1: var n = 0; var obj = {toLocaleString: function() {n++}}; Array.prototype[1] = obj; x = [obj]; x.
built-ins/Array/prototype/toReversed/holes-not-preserved.js # Actual [4, undefined, 2, undefined, 0] and expected [4, 3, 2, undefined, 0] should have the same con
built-ins/Array/prototype/toReversed/length-casted-to-zero.js # TypeError: Array.prototype.toReversed called on incompatible receiver a data object.
built-ins/Array/prototype/toReversed/length-exceeding-array-length-limit.js # TypeError: Only init object properties are supported.
built-ins/Array/prototype/toReversed/length-tolength.js # TypeError: Array.prototype.toReversed called on incompatible receiver a data object.
built-ins/Array/prototype/toReversed/this-value-boolean.js # TypeError: Array.prototype.toReversed called on incompatible receiver a boolean.
built-ins/Array/prototype/toSorted/holes-not-preserved.js # Actual [1, 3, 4, undefined, undefined] and expected [1, 2, 3, 4, undefined] should have the same con
built-ins/Array/prototype/toSorted/length-casted-to-zero.js # TypeError: Array.prototype.toSorted called on incompatible receiver a data object.
built-ins/Array/prototype/toSorted/length-exceeding-array-length-limit.js # TypeError: Only init object properties are supported.
built-ins/Array/prototype/toSorted/length-tolength.js # TypeError: Array.prototype.toSorted called on incompatible receiver a data object.
built-ins/Array/prototype/toSorted/this-value-boolean.js # TypeError: Array.prototype.toSorted called on incompatible receiver a boolean.
built-ins/Array/prototype/toSpliced/holes-not-preserved.js # Actual [0, undefined, 2, undefined, 4] and expected [0, undefined, 2, 3, 4] should have the same con
built-ins/Array/prototype/toSpliced/length-casted-to-zero.js # TypeError: Array.prototype.toSpliced called on incompatible receiver a data object.
built-ins/Array/prototype/toSpliced/length-clamped-to-2pow53minus1.js # TypeError: Array.prototype.toSpliced called on incompatible receiver a data object.
built-ins/Array/prototype/toSpliced/length-exceeding-array-length-limit.js # TypeError: Only init object properties are supported.
built-ins/Array/prototype/toSpliced/length-tolength.js # TypeError: Array.prototype.toSpliced called on incompatible receiver a data object.
built-ins/Array/prototype/toSpliced/this-value-boolean.js # TypeError: Array.prototype.toSpliced called on incompatible receiver a boolean.
built-ins/Array/prototype/toString/S15.4.4.2_A1_T4.js # Expected a Test262Error to be thrown but no exception was thrown at all
built-ins/Array/prototype/toString/S15.4.4.2_A3_T1.js # #1: Array.prototype[1] = 1; x = [0]; x.length = 2; x.toString() === "0,1". Actual: 0,
built-ins/Array/prototype/toString/call-with-boolean.js # TypeError: Array.prototype.toString called on incompatible receiver a boolean.
built-ins/Array/prototype/unshift/S15.4.4.13_A2_T1.js # Array.prototype.unshift called on incompatible receiver a data object.
built-ins/Array/prototype/unshift/S15.4.4.13_A2_T3.js # Array.prototype.unshift called on incompatible receiver a data object.
built-ins/Array/prototype/unshift/S15.4.4.13_A3_T2.js # Array.prototype.unshift called on incompatible receiver a data object.
built-ins/Array/prototype/unshift/S15.4.4.13_A4_T1.js # Array.prototype.unshift called on incompatible receiver a data object.
built-ins/Array/prototype/unshift/S15.4.4.13_A4_T2.js # #3: Array.prototype[0] = 1; x = []; x.length = 1; x.unshift(0); x[1] === 1. Actual: undefined
built-ins/Array/prototype/unshift/call-with-boolean.js # TypeError: Array.prototype.unshift called on incompatible receiver a boolean.
built-ins/Array/prototype/unshift/clamps-to-integer-limit.js # TypeError: Array.prototype.unshift called on incompatible receiver a data object.
built-ins/Array/prototype/unshift/length-near-integer-limit.js # TypeError: Only init object properties are supported.
built-ins/Array/prototype/with/length-exceeding-array-length-limit.js # TypeError: Only init object properties are supported.
built-ins/Array/prototype/with/length-tolength.js # TypeError: Array.prototype.with called on incompatible receiver a data object.
built-ins/Array/prototype/with/this-value-boolean.js # TypeError: Array.prototype.with called on incompatible receiver a boolean.
built-ins/Function/prototype/bind/15.3.4.5-2-6.js # TypeError: Object(number) wrapper objects are not supported; use the primitive value directly.
built-ins/Function/prototype/bind/15.3.4.5-20-2.js # Expected a TypeError to be thrown but no exception was thrown at all
built-ins/Function/prototype/bind/15.3.4.5-20-3.js # Expected a TypeError to be thrown but no exception was thrown at all
built-ins/Function/prototype/bind/15.3.4.5-21-2.js # Expected a TypeError to be thrown but no exception was thrown at all
built-ins/Function/prototype/bind/15.3.4.5-21-3.js # Expected a TypeError to be thrown but no exception was thrown at all
built-ins/Function/prototype/bind/S15.3.4.5_A1.js # baz() throws a TypeError exception Expected a TypeError to be thrown but no exception was thrown at
built-ins/Function/prototype/bind/S15.3.4.5_A2.js # baz() throws a TypeError exception Expected a TypeError to be thrown but no exception was thrown at
built-ins/Iterator/from/return-method-returns-iterator-result.js # Iterator next must be a function.
built-ins/Iterator/prototype/drop/limit-tonumber-throws.js # Expected a Test262Error but got a RangeError
built-ins/Iterator/prototype/drop/limit-tonumber.js # Iterator.prototype.drop expects a non-negative count, received NaN.
built-ins/Iterator/prototype/drop/this-non-callable-next.js # TypeError: Iterator next must be a function.
built-ins/Iterator/prototype/filter/this-non-callable-next.js # TypeError: Iterator next must be a function.
built-ins/Iterator/prototype/flatMap/this-non-callable-next.js # TypeError: Iterator next must be a function.
built-ins/Iterator/prototype/map/this-non-callable-next.js # TypeError: Iterator next must be a function.
built-ins/Iterator/prototype/take/limit-tonumber-throws.js # Expected a Test262Error but got a RangeError
built-ins/Iterator/prototype/take/limit-tonumber.js # Iterator.prototype.take expects a non-negative count, received NaN.
built-ins/Iterator/prototype/take/this-non-callable-next.js # TypeError: Iterator next must be a function.
language/arguments-object/10.6-13-c-1-s.js # Expected a TypeError to be thrown but no exception was thrown at all
language/arguments-object/10.6-14-c-4-s.js # Expected a TypeError to be thrown but no exception was thrown at all
language/arguments-object/10.6-2gs.js # Expected a TypeError to be thrown but no exception was thrown at all
language/arguments-object/S10.6_A3_T1.js # #1: arguments object doesn't exists
language/arguments-object/S10.6_A5_T3.js # #1: arguments object don't exists
language/arguments-object/S10.6_A5_T4.js # #1: arguments object don't exists
language/expressions/tagged-template/constructor-invocation.js # The called value cannot be constructed: user-defined constructors and classes are not supported.
language/expressions/tagged-template/template-object-frozen-strict.js # Expected a TypeError to be thrown but no exception was thrown at all
language/expressions/this/11.1.1-1.js # Expected SameValue(«undefined», «undefined») to be false
language/statements/async-generator/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/async-generator/dstr/ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/async-generator/dstr/dflt-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/async-generator/dstr/dflt-ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/async-generator/return-undefined-implicit-and-explicit.js # Actual ["tick 1", "tick 2", "g1 ret", "g2 ret", "g3 ret", "g4 ret"] and expected ["tick 1", "g1 ret"
language/statements/const/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/const/dstr/ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/for-await-of/async-func-decl-dstr-obj-empty-bool.js # TypeError: Object destructuring requires a data object or array value, received a boolean.
language/statements/for-await-of/async-func-decl-dstr-obj-empty-num.js # TypeError: Object destructuring requires a data object or array value, received a number.
language/statements/for-await-of/async-func-decl-dstr-obj-empty-string.js # TypeError: Object destructuring requires a data object or array value, received a string.
@@ -931,89 +213,48 @@ language/statements/for-await-of/async-gen-decl-dstr-obj-empty-num.js # TypeErr
language/statements/for-await-of/async-gen-decl-dstr-obj-empty-string.js # TypeError: Object destructuring requires a data object or array value, received a string.
language/statements/for-await-of/async-gen-decl-dstr-obj-rest-number.js # TypeError: Object destructuring requires a data object or array value, received a number.
language/statements/for-await-of/async-gen-decl-dstr-obj-rest-str-val.js # TypeError: Object destructuring requires a data object or array value, received a string.
language/statements/for-in/S12.6.4_A6.1.js # TypeError: FACTORY cannot be constructed: user-defined constructors and classes are not supported. C
language/statements/for-in/S12.6.4_A6.js # TypeError: FACTORY cannot be constructed: user-defined constructors and classes are not supported. C
language/statements/for-in/head-lhs-member.js # Unsupported for...in binding.
language/statements/for-of/dstr/array-elem-iter-rtrn-close-err.js # Iterator next must be a function.
language/statements/for-of/dstr/array-elem-iter-thrw-close-err.js # Expected SameValue(«1», «0») to be true
language/statements/for-of/dstr/array-elem-iter-thrw-close.js # Expected SameValue(«1», «0») to be true
language/statements/for-of/dstr/array-elem-trlg-iter-list-thrw-close-err.js # Expected SameValue(«1», «0») to be true
language/statements/for-of/dstr/array-elem-trlg-iter-list-thrw-close.js # Expected SameValue(«1», «0») to be true
language/statements/for-of/dstr/array-elem-trlg-iter-rest-rtrn-close-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
language/statements/for-of/dstr/array-elem-trlg-iter-rest-rtrn-close-null.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/for-of/dstr/array-elem-trlg-iter-rest-rtrn-close.js # Expected SameValue(«11», «1») to be true
language/statements/for-of/dstr/array-elem-trlg-iter-rest-thrw-close-err.js # Expected SameValue(«11», «1») to be true
language/statements/for-of/dstr/array-elem-trlg-iter-rest-thrw-close.js # Expected SameValue(«11», «1») to be true
language/statements/for-of/dstr/array-rest-iter-rtrn-close-err.js # Iterator next must be a function.
language/statements/for-of/dstr/array-rest-iter-rtrn-close-null.js # Iterator next must be a function.
language/statements/for-of/dstr/array-rest-iter-rtrn-close.js # Test262Error
language/statements/for-of/dstr/array-rest-iter-thrw-close-err.js # Expected SameValue(«11», «0») to be true
language/statements/for-of/dstr/array-rest-iter-thrw-close.js # Expected SameValue(«11», «0») to be true
language/statements/for-of/dstr/array-rest-lref-err.js # Expected SameValue(«1», «0») to be true
language/statements/for-of/dstr/const-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/for-of/dstr/const-ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/for-of/dstr/let-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/for-of/dstr/let-ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/for-of/dstr/obj-empty-bool.js # Object destructuring requires a data object or array value, received a boolean.
language/statements/for-of/dstr/obj-empty-num.js # Object destructuring requires a data object or array value, received a number.
language/statements/for-of/dstr/obj-empty-string.js # Object destructuring requires a data object or array value, received a string.
language/statements/for-of/dstr/obj-rest-number.js # Object destructuring requires a data object or array value, received a number.
language/statements/for-of/dstr/obj-rest-str-val.js # Object destructuring requires a data object or array value, received a string.
language/statements/for-of/dstr/var-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/for-of/dstr/var-ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/for-of/throw-from-catch.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
language/statements/for-of/throw-from-finally.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
language/statements/for-of/throw.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
language/statements/for/dstr/const-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/for/dstr/const-ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/for/dstr/let-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/for/dstr/let-ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/for/dstr/var-ary-init-iter-get-err-array-prototype.js # Expected a TypeError but got a ReferenceError
language/statements/for/dstr/var-ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/function/13.2-1-s.js # TypeError: foo cannot be constructed: user-defined constructors and classes are not supported. Call
language/statements/function/13.2-19-b-3gs.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/function/13.2-2-s.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/function/13.2-3-s.js # TypeError: foo cannot be constructed: user-defined constructors and classes are not supported. Call
language/statements/function/13.2-4-s.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/function/S13.2.2_A10.js # #1: var obj = new FACTORY() does not lead to throwing exception. Actual: Exception is TypeError: FAC
language/statements/function/S13.2.2_A12.js # #1: var obj = new FACTORY() does not lead to throwing exception. Actual: Exception is TypeError: FAC
language/statements/function/S13.2.2_A15_T1.js # TypeError: __FACTORY cannot be constructed: user-defined constructors and classes are not supported.
language/statements/function/S13.2.2_A15_T2.js # TypeError: __FACTORY cannot be constructed: user-defined constructors and classes are not supported.
language/statements/function/S13.2.2_A15_T3.js # TypeError: __FACTORY cannot be constructed: user-defined constructors and classes are not supported.
language/statements/function/S13.2.2_A15_T4.js # TypeError: __FACTORY cannot be constructed: user-defined constructors and classes are not supported.
language/statements/function/S13.2.2_A16_T1.js # TypeError: The called value cannot be constructed: user-defined constructors and classes are not sup
language/statements/function/S13.2.2_A16_T2.js # TypeError: The called value cannot be constructed: user-defined constructors and classes are not sup
language/statements/function/S13.2.2_A16_T3.js # TypeError: The called value cannot be constructed: user-defined constructors and classes are not sup
language/statements/function/S13.2.2_A1_T1.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
language/statements/function/S13.2.2_A1_T2.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
language/statements/function/S13.2.2_A2.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
language/statements/function/S13.2.2_A3_T1.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
language/statements/function/S13.2.2_A3_T2.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
language/statements/function/S13.2.2_A4_T1.js # TypeError: __FACTORY cannot be constructed: user-defined constructors and classes are not supported.
language/statements/function/S13.2.2_A4_T2.js # TypeError: __FACTORY cannot be constructed: user-defined constructors and classes are not supported.
language/statements/function/S13.2.2_A5_T1.js # TypeError: __FACTORY cannot be constructed: user-defined constructors and classes are not supported.
language/statements/function/S13.2.2_A5_T2.js # TypeError: __FACTORY cannot be constructed: user-defined constructors and classes are not supported.
language/statements/function/S13.2.2_A6_T1.js # TypeError: __func cannot be constructed: user-defined constructors and classes are not supported. Ca
language/statements/function/S13.2.2_A6_T2.js # TypeError: __func cannot be constructed: user-defined constructors and classes are not supported. Ca
language/statements/function/S13.2.2_A7_T1.js # TypeError: __func cannot be constructed: user-defined constructors and classes are not supported. Ca
language/statements/function/S13.2.2_A7_T2.js # TypeError: __func cannot be constructed: user-defined constructors and classes are not supported. Ca
language/statements/function/S13.2.2_A8_T1.js # TypeError: __func cannot be constructed: user-defined constructors and classes are not supported. Ca
language/statements/function/S13.2.2_A8_T2.js # TypeError: __func cannot be constructed: user-defined constructors and classes are not supported. Ca
language/statements/function/S13.2_A1_T1.js # #1: __func.prototype !== undefined
language/statements/function/S13.2_A1_T2.js # #1: __func.prototype !== undefined
language/statements/function/S13.2_A4_T1.js # Unknown identifier '…'.
language/statements/function/S13.2_A4_T2.js # #1: typeof __gunc.prototype === '…'. Actual: typeof __gunc.prototype ===undefined
language/statements/function/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/function/dstr/ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/function/dstr/dflt-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/function/dstr/dflt-ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/generators/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/generators/dstr/ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/generators/dstr/dflt-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/generators/dstr/dflt-ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/generators/restricted-properties.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/labeled/value-await-non-module.js # Failed to parse TypeScript: Expression expected.
language/statements/let/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/let/dstr/ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/return/S12.9_A1_T1.js # expected SyntaxError but the program ran
language/statements/return/S12.9_A1_T10.js # expected SyntaxError but the program ran
language/statements/return/S12.9_A1_T2.js # expected SyntaxError but the program ran
@@ -1026,10 +267,5 @@ language/statements/return/S12.9_A1_T8.js # expected SyntaxError but the progra
language/statements/return/S12.9_A1_T9.js # expected SyntaxError but the program ran
language/statements/switch/S12.11_A1_T4.js # Switch discriminants must be data values.
language/statements/switch/scope-lex-open-dflt.js # Switch discriminants must be data values.
language/statements/try/S12.14_A17.js # TypeError: Integer cannot be constructed: user-defined constructors and classes are not supported. C
language/statements/try/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/try/dstr/ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
language/statements/variable/S12.2_A11.js # TypeError: Cannot read properties of undefined (reading '…').
language/statements/variable/S12.2_A9.js # #1: When using property attributes, {DontEnum} not used
language/statements/variable/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
language/statements/variable/dstr/ary-ptrn-elem-id-iter-val-array-prototype.js # Expected SameValue(«3», «42») to be true
+3 -2
View File
@@ -98,7 +98,8 @@
"@types/bun": "catalog:",
"@types/node": "catalog:",
"@types/which": "3.0.4",
"drizzle-kit": "catalog:"
"drizzle-kit": "catalog:",
"fast-check": "catalog:"
},
"dependencies": {
"@ai-sdk/cohere": "3.0.27",
@@ -127,7 +128,7 @@
"drizzle-orm": "catalog:",
"effect": "catalog:",
"fuzzysort": "3.1.0",
"gitlab-ai-provider": "6.16.0",
"gitlab-ai-provider": "6.12.1",
"google-auth-library": "10.5.0",
"gray-matter": "4.0.3",
"htmlparser2": "8.0.2",
+2 -12
View File
@@ -1,8 +1,8 @@
{
"version": "7",
"dialect": "sqlite",
"id": "e98619ef-c334-45e3-8c48-9932ed1ef290",
"prevIds": ["be60f352-8da1-40e1-8d70-dc41121cfbc5"],
"id": "be60f352-8da1-40e1-8d70-dc41121cfbc5",
"prevIds": ["3fb67508-0196-4bae-b2bd-c08ece7583fd"],
"ddl": [
{
"name": "account_state",
@@ -700,16 +700,6 @@
"entityType": "columns",
"table": "project"
},
{
"type": "integer",
"notNull": true,
"autoincrement": false,
"default": "0",
"generated": null,
"name": "time_active",
"entityType": "columns",
"table": "project"
},
{
"type": "text",
"notNull": true,
+14 -39
View File
@@ -705,7 +705,7 @@ function metadataProviderOptions(input: ProviderMetadata | undefined): SharedV3P
}
function streamLanguage(language: LanguageModelV3, options: LanguageModelV3CallOptions, http?: HttpMiddleware) {
const state: StreamState = { step: 0, toolNames: {}, open: {} }
const state = { step: 0, toolNames: {} as Record<string, string> }
return Stream.concat(
Stream.make(LLMEvent.stepStart({ index: state.step })),
Stream.unwrap(
@@ -731,16 +731,8 @@ function streamLanguage(language: LanguageModelV3, options: LanguageModelV3CallO
)
}
type Fragment = "text" | "reasoning"
type StreamState = {
step: number
toolNames: Record<string, string>
open: Partial<Record<Fragment, string>>
}
function streamPartEvents(
state: StreamState,
state: { step: number; toolNames: Record<string, string> },
event: LanguageModelV3StreamPart,
): Effect.Effect<ReadonlyArray<LLMEvent>, AIError> {
switch (event.type) {
@@ -752,10 +744,11 @@ function streamPartEvents(
case "tool-approval-request":
return Effect.succeed([])
case "text-start":
return Effect.succeed(openFragment(state, "text", event.id, providerMetadata(event.providerMetadata)))
return Effect.succeed([
LLMEvent.textStart({ id: event.id, providerMetadata: providerMetadata(event.providerMetadata) }),
])
case "text-delta":
return Effect.succeed([
...openFragment(state, "text", event.id),
LLMEvent.textDelta({
id: event.id,
text: event.delta,
@@ -763,12 +756,15 @@ function streamPartEvents(
}),
])
case "text-end":
return Effect.succeed(closeFragment(state, "text", event.id, providerMetadata(event.providerMetadata)))
return Effect.succeed([
LLMEvent.textEnd({ id: event.id, providerMetadata: providerMetadata(event.providerMetadata) }),
])
case "reasoning-start":
return Effect.succeed(openFragment(state, "reasoning", event.id, providerMetadata(event.providerMetadata)))
return Effect.succeed([
LLMEvent.reasoningStart({ id: event.id, providerMetadata: providerMetadata(event.providerMetadata) }),
])
case "reasoning-delta":
return Effect.succeed([
...openFragment(state, "reasoning", event.id),
LLMEvent.reasoningDelta({
id: event.id,
text: event.delta,
@@ -776,7 +772,9 @@ function streamPartEvents(
}),
])
case "reasoning-end":
return Effect.succeed(closeFragment(state, "reasoning", event.id, providerMetadata(event.providerMetadata)))
return Effect.succeed([
LLMEvent.reasoningEnd({ id: event.id, providerMetadata: providerMetadata(event.providerMetadata) }),
])
case "tool-input-start":
state.toolNames[event.id] = event.toolName
return Effect.succeed([
@@ -853,29 +851,6 @@ function streamPartEvents(
}
}
// Session persists one open text and one open reasoning fragment at a time, while AI SDK providers may overlap,
// repeat, or omit fragment boundaries. Like the native protocol lifecycles, a start or delta for another fragment
// closes the open one, repeated starts are ignored, and ends for fragments that are not open are dropped.
function openFragment(state: StreamState, kind: Fragment, id: string, providerMetadata?: ProviderMetadata) {
const open = state.open[kind]
if (open === id) return []
state.open[kind] = id
const start =
kind === "text" ? LLMEvent.textStart({ id, providerMetadata }) : LLMEvent.reasoningStart({ id, providerMetadata })
if (open === undefined) return [start]
return [fragmentEnd(kind, open), start]
}
function closeFragment(state: StreamState, kind: Fragment, id: string, providerMetadata?: ProviderMetadata) {
if (state.open[kind] !== id) return []
state.open[kind] = undefined
return [fragmentEnd(kind, id, providerMetadata)]
}
function fragmentEnd(kind: Fragment, id: string, providerMetadata?: ProviderMetadata) {
return kind === "text" ? LLMEvent.textEnd({ id, providerMetadata }) : LLMEvent.reasoningEnd({ id, providerMetadata })
}
function usage(input: Extract<LanguageModelV3StreamPart, { type: "finish" }>["usage"]): UsageInput | undefined {
const output = {
inputTokens: input.inputTokens.total,
+3 -2
View File
@@ -99,7 +99,7 @@ export const layer = (options?: Options) =>
const wellknown = yield* WellKnown.Service
const reloadLock = Semaphore.makeUnsafe(1)
const updateLock = Semaphore.makeUnsafe(1)
const decodeOptions = { errors: "all", onExcessProperty: "ignore", propertyOrder: "original" } as const
const decodeOptions = { errors: "all", onExcessProperty: "ignore" } as const
const decodeInfo = Schema.decodeUnknownOption(Info, decodeOptions)
const parseInfo = Effect.fn("Config.parseInfo")(function* (text: string, source: string) {
const errors: ParseError[] = []
@@ -330,7 +330,8 @@ export const layer = (options?: Options) =>
function* (patch: Patch) {
const directory = initial.global ?? AbsolutePath.make(globalService.config)
const candidates = ConfigDiscovery.names.map((name) => path.join(directory, name))
const filepath = (yield* Effect.filter(candidates, fs.isFile)).at(-1) ?? path.join(directory, "opencode.jsonc")
const filepath =
(yield* Effect.filter(candidates, fs.isFile)).at(-1) ?? path.join(directory, "opencode.jsonc")
const text = (yield* fs.readFileStringSafe(filepath)) ?? "{}\n"
const updated = yield* Effect.try({
try: () =>
+1 -1
View File
@@ -42,7 +42,7 @@ export type Result =
}
| { readonly type: "rejected"; readonly diagnostics: readonly Diagnostic[] }
const options = { errors: "all", onExcessProperty: "ignore", propertyOrder: "original" } as const
const options = { errors: "all", onExcessProperty: "ignore" } as const
const unsupportedTopLevel = ["logLevel", "server", "subagent_depth", "layout"] as const
const unsupportedExperimental = [
"disable_paste_summary",
+2 -2
View File
@@ -196,11 +196,11 @@ function decode(file: { directory: string; filepath: string; primary: boolean },
const agent = legacy
? Option.getOrUndefined(
Option.map(
decodeLegacyAgent({ name, ...markdown.data, prompt: body }, { errors: "all", propertyOrder: "original" }),
decodeLegacyAgent({ name, ...markdown.data, prompt: body }, { errors: "all" }),
ConfigMigrateV1.migrateAgent,
),
)
: Option.getOrUndefined(decodeAgent({ ...data, system: body }, { errors: "all", propertyOrder: "original" }))
: Option.getOrUndefined(decodeAgent({ ...data, system: body }, { errors: "all" }))
if (!agent) return
const info = Option.getOrUndefined(
decodeConfig({
-2
View File
@@ -46,7 +46,6 @@ import m43 from "./migration/20260812213948_worktree.js"
import m44 from "./migration/20260819222447_session_viewed_state.js"
import m45 from "./migration/20260823191254_nullable_workspace_binding.js"
import m46 from "./migration/20260910120000_clear_v1_session_permission.js"
import m47 from "./migration/20260923013825_project_time_active.js"
export const migrations = [
m00,
@@ -96,5 +95,4 @@ export const migrations = [
m44,
m45,
m46,
m47,
] satisfies DatabaseMigration.Migration[]
@@ -1,14 +0,0 @@
import { Effect } from "effect"
import type { DatabaseMigration } from "../migration.js"
const migration: DatabaseMigration.Migration = {
id: "20260923013825_project_time_active",
up(tx) {
return Effect.gen(function* () {
yield* tx.run(`ALTER TABLE \`project\` ADD \`time_active\` integer DEFAULT 0 NOT NULL;`)
yield* tx.run(`UPDATE \`project\` SET \`time_active\` = \`time_updated\`;`)
})
},
}
export default migration
-1
View File
@@ -110,7 +110,6 @@ const schema: Omit<DatabaseMigration.Migration, "id"> = {
\`time_created\` integer NOT NULL,
\`time_updated\` integer NOT NULL,
\`time_initialized\` integer,
\`time_active\` integer DEFAULT 0 NOT NULL,
\`sandboxes\` text NOT NULL,
\`commands\` text
);
@@ -523,8 +523,8 @@ export function run(options: Options = {}): Effect.Effect<RunResult, never, Data
if (!(yield* hasLegacySessions(db))) return { status: "completed" as const }
const now = Date.now()
yield* db.run(sql`
INSERT OR IGNORE INTO project (id, worktree, time_created, time_updated, time_active, sandboxes)
VALUES (${Project.ID.global}, ${path.parse(global.data).root}, ${now}, ${now}, ${now}, '[]')
INSERT OR IGNORE INTO project (id, worktree, time_created, time_updated, sandboxes)
VALUES (${Project.ID.global}, ${path.parse(global.data).root}, ${now}, ${now}, '[]')
`)
if (state === undefined)
yield* db
@@ -753,11 +753,11 @@ function importNextDatabase(
yield* tx.run(sql`
INSERT OR IGNORE INTO project (
id, worktree, vcs, name, icon_url, icon_url_override, icon_color,
time_created, time_updated, time_initialized, time_active, sandboxes, commands
time_created, time_updated, time_initialized, sandboxes, commands
) VALUES (
${project.id}, ${project.worktree}, ${project.vcs}, ${project.name}, ${project.icon_url},
${project.icon_url_override}, ${project.icon_color}, ${project.time_created}, ${project.time_updated},
${project.time_initialized}, ${project.time_updated}, ${project.sandboxes}, ${project.commands}
${project.time_initialized}, ${project.sandboxes}, ${project.commands}
)
`)
const existing = yield* tx
@@ -48,10 +48,9 @@ const proxy = (value: string, environment: Environment = process.env) => {
)
}
const constructorOptions = (input: string | Array<string> | undefined): WebSocketOptions => {
const constructorOptions = (input: Socket.WebSocketConstructorOptions | undefined): WebSocketOptions => {
if (typeof input === "string" || Array.isArray(input)) return { protocols: input }
// AI routes pass handshake options through Effect's browser-shaped constructor.
return (input ?? {}) as WebSocketOptions
return { headers: input?.headers === undefined ? undefined : Headers.fromInput(input.headers) }
}
const proxyAgent = (url: string, selectedProxy: string | undefined) => {
+2 -18
View File
@@ -1,18 +1,13 @@
export * as LocationLifecycle from "./location-lifecycle.js"
import { Context, Effect, Layer, Schema } from "effect"
import { Context, Effect, Layer } from "effect"
import { makeLocationNode } from "@opencode/util/effect/app-node"
import { LocationEvent } from "@opencode/schema/location-event"
import { Bus } from "./bus.js"
import { Form } from "./form.js"
import { Location } from "./location.js"
import { LocationServiceMap } from "./location-service-map.js"
import { Permission } from "./permission.js"
import { Project } from "./project.js"
import { Rpc } from "./rpc.js"
import { SessionEvent } from "./session/event.js"
const isSessionEvent = Schema.is(SessionEvent.Durable)
export class Service extends Context.Service<
Service,
@@ -27,17 +22,6 @@ const layer = Layer.effect(
const permission = yield* Permission.Service
const forms = yield* Form.Service
const rpc = yield* Rpc.Service
const project = yield* Project.Service
const scope = yield* Effect.scope
yield* project.activate(location.project.id)
const unsubscribe = yield* bus.listen((event) => {
if (!isSessionEvent(event) || !event.location) return Effect.void
const ref = LocationServiceMap.canonical(event.location)
if (ref.directory !== location.directory || ref.workspaceID !== location.workspaceID) return Effect.void
// Listeners run inside publish; keep the write and its Project event off that path.
return project.activate(location.project.id).pipe(Effect.forkIn(scope), Effect.asVoid)
})
yield* Effect.addFinalizer(() => unsubscribe)
let closed = false
const shutdown = yield* Effect.cached(
Effect.gen(function* () {
@@ -64,5 +48,5 @@ const layer = Layer.effect(
export const node = makeLocationNode({
service: Service,
layer,
deps: [Bus.node, Location.node, Permission.node, Project.node, Form.node, Rpc.node],
deps: [Bus.node, Location.node, Permission.node, Form.node, Rpc.node],
})
+3 -24
View File
@@ -2,7 +2,7 @@ export * as Project from "./project.js"
import { Context, Effect, Layer, Schema } from "effect"
import { ChildProcess } from "effect/unstable/process"
import { and, asc, desc, eq, gte, isNull, lte, sql } from "drizzle-orm"
import { and, asc, desc, eq, gte, isNull, lte } from "drizzle-orm"
import path from "path"
import { AbsolutePath } from "./schema.js"
import { Bus } from "./bus.js"
@@ -57,13 +57,9 @@ export const root = Effect.fn("Project.root")(function* (
)
})
const ACTIVATE_INTERVAL = 60_000
export interface Interface {
readonly list: () => Effect.Effect<ReadonlyArray<Info>>
readonly update: (input: UpdateInput) => Effect.Effect<Info, NotFoundError>
/** Records Project activity for recency ordering, at most once per minute per Project. */
readonly activate: (projectID: ID) => Effect.Effect<void>
/** Resolves and persists the owning Project. */
readonly resolve: (input: AbsolutePath, options?: { readonly discovery?: boolean }) => Effect.Effect<Resolved>
}
@@ -89,7 +85,6 @@ function fromRow(row: typeof ProjectTable.$inferSelect): Info {
time: {
created: row.time_created,
updated: row.time_updated,
active: row.time_active,
},
sandboxes: row.sandboxes,
}
@@ -206,7 +201,7 @@ const layer = Layer.effect(
const rows = yield* db
.select()
.from(ProjectTable)
.orderBy(desc(ProjectTable.time_active), asc(ProjectTable.id))
.orderBy(desc(ProjectTable.time_updated), asc(ProjectTable.id))
.all()
.pipe(Effect.orDie)
return rows.map(fromRow)
@@ -238,22 +233,6 @@ const layer = Layer.effect(
return project
})
const activated = new Map<ID, number>()
const activate = Effect.fn("Project.activate")(function* (projectID: ID) {
const now = Date.now()
if (now - (activated.get(projectID) ?? 0) < ACTIVATE_INTERVAL) return
activated.set(projectID, now)
const row = yield* db
.update(ProjectTable)
// Activity is not a metadata edit, so keep time_updated out of the implicit bump.
.set({ time_active: now, time_updated: sql`${ProjectTable.time_updated}` })
.where(eq(ProjectTable.id, projectID))
.returning()
.get()
.pipe(Effect.orDie)
if (row) yield* bus.publish(ProjectSchema.Event.Updated, fromRow(row))
})
const cached = Effect.fnUntraced(function* (dir: string) {
return yield* fs.readFileString(path.join(dir, "opencode")).pipe(
Effect.map((value) => value.trim()),
@@ -382,7 +361,7 @@ const layer = Layer.effect(
})
})
return Service.of({ list, update, activate, resolve })
return Service.of({ list, update, resolve })
}),
)
-4
View File
@@ -19,10 +19,6 @@ export const ProjectTable = sqliteTable("project", {
icon_color: text(),
...Timestamps,
time_initialized: integer(),
time_active: integer()
.notNull()
.default(0)
.$defaultFn(() => Date.now()),
sandboxes: absoluteArrayColumn().notNull(),
commands: text({ mode: "json" }).$type<{ start?: string }>(),
})
+22 -5
View File
@@ -1,7 +1,7 @@
import type { ToolDefinition } from "@opencode/ai"
import { Tool } from "@opencode/schema/tool"
import type { StandardJSONSchemaV1, StandardSchemaV1 } from "@standard-schema/spec"
import { Cache, Effect, JsonSchema, Schema, SchemaIssue, SchemaRepresentation } from "effect"
import { Cache, Effect, JsonPointer, JsonSchema, Schema, SchemaIssue, SchemaRepresentation } from "effect"
import { $ZodType, toJSONSchema } from "zod/v4/core"
const formatEffectIssues = SchemaIssue.makeFormatterStandardSchemaV1()
@@ -155,7 +155,24 @@ const validateStandard = (
const inputJsonSchema = (schema: Tool.ValueSchema<any>): JsonSchema.JsonSchema => {
if (schema === undefined || schema === null) return {}
if (isStandardSchema(schema)) return standardJsonSchema(schema, "input")
return Schema.isSchema(schema) ? toJsonSchema(schema) : schema
if (!Schema.isSchema(schema)) return schema
const json = toJsonSchema(schema)
// Empty Effect structs describe non-null values, but tool parameters must be
// objects. Normalize after inlining named schemas, retaining their metadata.
if (
schema.ast._tag === "Objects" &&
schema.ast.propertySignatures.length === 0 &&
schema.ast.indexSignatures.length === 0 &&
schema.ast.encoding === undefined &&
schema.ast.checks === undefined &&
isRecord(json.not) &&
json.not.type === "null" &&
Object.keys(json.not).length === 1
) {
const { not: _, ...metadata } = json
return { ...metadata, type: "object", properties: {}, additionalProperties: false }
}
return json
}
const outputJsonSchema = (schema: Tool.ValueSchema<any>): JsonSchema.JsonSchema => {
@@ -170,7 +187,7 @@ const standardJsonSchema = (schema: StandardSchemaV1<any, any>, io: "input" | "o
}
const toJsonSchema = (schema: Schema.Top): JsonSchema.JsonSchema => {
const document = Schema.toJsonSchemaDocument(schema)
const document = Schema.toJsonSchemaDocument(schema, { onExcessProperty: "error" })
// Effect emits valid JSON Schema that some inference providers handle poorly. Simplify it
// without changing validation: `{ type: "integer", allOf: [{ minimum: 0 }] }` becomes
// `{ type: "integer", minimum: 0 }` only when no keyword would be overwritten. Named schemas
@@ -220,8 +237,8 @@ const inlineLocalReferences = (
const localDefinitions = definitions ?? (isRecord(value.$defs) ? value.$defs : undefined)
if (typeof value.$ref === "string" && localDefinitions) {
const segment = value.$ref.match(/^#\/\$defs\/([^/]+)$/)?.[1]
const name = segment?.replaceAll("~1", "/").replaceAll("~0", "~")
const tokens = JsonPointer.parseUriFragment(value.$ref)
const name = tokens?.length === 2 && tokens[0] === "$defs" ? tokens[1] : undefined
if (name && !seen.has(name)) {
const target = localDefinitions[name]
if (target) {
+2 -4
View File
@@ -6,16 +6,15 @@ const decode = Schema.decodeUnknownOption(
Schema.Struct({
name: Schema.optional(Schema.String),
_tag: Schema.optional(Schema.String),
message: Schema.optional(Schema.String),
code: Schema.optional(Schema.Union([Schema.String, Schema.Number])),
errno: Schema.optional(Schema.Number),
cause: Schema.optional(Schema.Unknown),
}),
)
/** Stacks are omitted; each entry keeps the classification and message of one error in the cause chain. */
/** Error messages, stacks and SQL parameters may contain credentials. Retain only diagnostic classifications. */
export function from(error: unknown) {
const errors: { type: string; message?: string; code?: string | number; errno?: number }[] = []
const errors: { type: string; code?: string | number; errno?: number }[] = []
const seen = new Set<unknown>()
while (error && !seen.has(error) && errors.length < 8) {
seen.add(error)
@@ -23,7 +22,6 @@ export function from(error: unknown) {
if (Option.isNone(result)) break
errors.push({
type: result.value._tag ?? (error instanceof Error ? error.name : result.value.name) ?? "unknown",
message: result.value.message || undefined,
code: result.value.code,
errno: result.value.errno,
})
+1 -1
View File
@@ -13,7 +13,7 @@ import { ConfigProviderOptionsV1 } from "./provider-options.js"
import { Provider } from "../../provider.js"
import { Model } from "../../model.js"
const decodeOptions = { errors: "all", onExcessProperty: "ignore", propertyOrder: "original" } as const
const decodeOptions = { errors: "all", onExcessProperty: "ignore" } as const
const decodeInfo = Schema.decodeUnknownSync(Schema.fromJsonString(Info), decodeOptions)
const encodeInfo = Schema.encodeSync(Info)
const decodeAgent = Schema.decodeUnknownSync(Schema.fromJsonString(ConfigAgent.Info), decodeOptions)
+2 -3
View File
@@ -11,9 +11,8 @@ export type Object = Schema.Schema.Type<typeof Object>
export const Rule = Schema.Union([Action, Object]).annotate({ identifier: "PermissionRuleConfig" })
export type Rule = Schema.Schema.Type<typeof Rule>
// Known permission keys get explicit types in the Effect schema for generated
// docs/types. Runtime config parsing uses Effect's `propertyOrder: "original"`
// parse option so user key order is preserved for permission precedence.
// Known permission keys get explicit types in the Effect schema for generated docs/types.
// StructWithRest also accepts custom permission names.
const InputObject = Schema.StructWithRest(
Schema.Struct({
read: Schema.optional(Rule),
-84
View File
@@ -385,90 +385,6 @@ it.effect("routes AI Gateway model options by upstream prefix", () =>
}),
)
it.effect("closes the open AI SDK reasoning part when the next one starts", () =>
Effect.gen(function* () {
// AI SDK OpenAI Responses can start summary part 1 before part 0 ends, then end both at item completion (#50662).
const aisdk = yield* AISDK.Service
yield* aisdk.hook.sdk((event) => {
event.sdk = {
languageModel: () =>
streamModel([
{ type: "reasoning-start", id: "rs_1:0", providerMetadata: { gateway: { generationId: "gen_1" } } },
{ type: "reasoning-start", id: "rs_1:1" },
{ type: "reasoning-delta", id: "rs_1:1", delta: "Second summary" },
{ type: "reasoning-end", id: "rs_1:0", providerMetadata: { gateway: { encrypted: "late" } } },
{ type: "reasoning-end", id: "rs_1:1", providerMetadata: { gateway: { encrypted: "final" } } },
{ type: "finish", finishReason: { unified: "stop", raw: "stop" }, usage },
]),
}
})
const resolved = yield* aisdk.model(model("@ai-sdk/gateway"))
const response = yield* LLMClient.generate(LLM.request({ model: resolved, prompt: "Think" })).pipe(
Effect.provide(client),
)
expect(response.events.filter((event) => event.type.startsWith("reasoning-"))).toEqual([
{ type: "reasoning-start", id: "rs_1:0", providerMetadata: { gateway: { generationId: "gen_1" } } },
{ type: "reasoning-end", id: "rs_1:0" },
{ type: "reasoning-start", id: "rs_1:1", providerMetadata: undefined },
{ type: "reasoning-delta", id: "rs_1:1", text: "Second summary", providerMetadata: undefined },
{ type: "reasoning-end", id: "rs_1:1", providerMetadata: { gateway: { encrypted: "final" } } },
])
}),
)
it.effect("normalizes repeated, reopened, and overlapping AI SDK fragment boundaries", () =>
Effect.gen(function* () {
const aisdk = yield* AISDK.Service
yield* aisdk.hook.sdk((event) => {
event.sdk = {
languageModel: () =>
streamModel([
// Older xAI Responses repeat the start for every summary part.
{ type: "reasoning-start", id: "rs_1" },
{ type: "reasoning-start", id: "rs_1" },
{ type: "reasoning-delta", id: "rs_1", delta: "First" },
{ type: "reasoning-end", id: "rs_1" },
// xAI Chat keeps streaming an ended reasoning id after an empty tool_calls chunk.
{ type: "reasoning-delta", id: "rs_1", delta: "Second" },
{ type: "reasoning-end", id: "rs_1" },
// xAI Responses ends every message item only when the stream flushes.
{ type: "text-start", id: "msg_1" },
{ type: "text-delta", id: "msg_1", delta: "One" },
{ type: "text-start", id: "msg_2" },
{ type: "text-delta", id: "msg_2", delta: "Two" },
{ type: "text-end", id: "msg_1" },
{ type: "text-end", id: "msg_2" },
{ type: "finish", finishReason: { unified: "stop", raw: "stop" }, usage },
]),
}
})
const resolved = yield* aisdk.model(model("@ai-sdk/gateway"))
const response = yield* LLMClient.generate(LLM.request({ model: resolved, prompt: "Think" })).pipe(
Effect.provide(client),
)
expect(
response.events.filter((event) => event.type.startsWith("reasoning-") || event.type.startsWith("text-")),
).toMatchObject([
{ type: "reasoning-start", id: "rs_1" },
{ type: "reasoning-delta", id: "rs_1", text: "First" },
{ type: "reasoning-end", id: "rs_1" },
{ type: "reasoning-start", id: "rs_1" },
{ type: "reasoning-delta", id: "rs_1", text: "Second" },
{ type: "reasoning-end", id: "rs_1" },
{ type: "text-start", id: "msg_1" },
{ type: "text-delta", id: "msg_1", text: "One" },
{ type: "text-end", id: "msg_1" },
{ type: "text-start", id: "msg_2" },
{ type: "text-delta", id: "msg_2", text: "Two" },
{ type: "text-end", id: "msg_2" },
])
}),
)
it.effect("projects replay metadata onto AI SDK prompt parts", () =>
Effect.gen(function* () {
const aisdk = yield* AISDK.Service
+16 -11
View File
@@ -2,7 +2,7 @@ import path from "path"
import fs from "fs/promises"
import { describe, expect, test } from "bun:test"
import { Effect, Fiber, Layer, Logger, Schema, Stream } from "effect"
import { FastCheck } from "effect/testing"
import { Arbitrary } from "effect/unstable/arbitrary"
import { Config } from "@opencode/core/config"
import { Directory, Document, Event, Info } from "@opencode/schema/config"
import { ConfigModel } from "@opencode/schema/config/model"
@@ -632,17 +632,22 @@ describe("Config", () => {
})
test("migrates arbitrary v1 configuration into valid v2 configuration", () => {
FastCheck.assert(
FastCheck.property(Schema.toArbitrary(ConfigV1.Info)(FastCheck), (info) => {
const parsed = Schema.decodeUnknownSync(ConfigV1.Info)(
Schema.decodeUnknownSync(Schema.fromJsonString(Schema.Unknown))(
Schema.encodeUnknownSync(Schema.fromJsonString(Schema.Unknown))(info),
),
)
Schema.decodeUnknownSync(Info)(ConfigMigrateV1.migrate(parsed), { errors: "all" })
}),
{ numRuns: 100 },
const result = Effect.runSync(
Arbitrary.checkEffect(
Arbitrary.schema(ConfigV1.Info),
(info) => {
const parsed = Schema.decodeUnknownSync(ConfigV1.Info)(
Schema.decodeUnknownSync(Schema.fromJsonString(Schema.Unknown))(
Schema.encodeUnknownSync(Schema.fromJsonString(Schema.Unknown))(info),
),
)
Schema.decodeUnknownSync(Info)(ConfigMigrateV1.migrate(parsed), { errors: "all" })
return true
},
{ runs: 100 },
),
)
expect(Arbitrary.formatCheckFailure(result)).toBeUndefined()
}, 30_000)
test("migrates the v1 experimental subagent depth", () => {
+17 -12
View File
@@ -1,10 +1,10 @@
import { describe, expect, test } from "bun:test"
import { Duration, Schema } from "effect"
import { FastCheck } from "effect/testing"
import { Duration, Effect, Schema } from "effect"
import { Arbitrary } from "effect/unstable/arbitrary"
import { ConfigNormalize } from "@opencode/core/config/normalize"
import { Info } from "@opencode/schema/config"
const options = { errors: "all", onExcessProperty: "ignore", propertyOrder: "original" } as const
const options = { errors: "all", onExcessProperty: "ignore" } as const
function normalized(input: unknown) {
const result = ConfigNormalize.normalize(input)
@@ -80,16 +80,21 @@ describe("ConfigNormalize", () => {
})
test("preserves arbitrary JSON-round-tripped native configuration", () => {
FastCheck.assert(
FastCheck.property(Schema.toArbitrary(Info)(FastCheck), (info) => {
const source = JSON.parse(JSON.stringify(Schema.encodeSync(Info)(info)))
const result = normalized(source)
expect(Schema.decodeUnknownSync(Info)(result.encoded)).toEqual(
Schema.decodeUnknownSync(Info)(withoutEmptyCompatibilityContainers(source)),
)
}),
{ numRuns: 100 },
const result = Effect.runSync(
Arbitrary.checkEffect(
Arbitrary.schema(Info),
(info) => {
const source = JSON.parse(JSON.stringify(Schema.encodeSync(Info)(info)))
const result = normalized(source)
expect(Schema.decodeUnknownSync(Info)(result.encoded)).toEqual(
Schema.decodeUnknownSync(Info)(withoutEmptyCompatibilityContainers(source)),
)
return true
},
{ runs: 100 },
),
)
expect(Arbitrary.formatCheckFailure(result)).toBeUndefined()
})
test("merges named maps by entry and gives valid native entries precedence", () => {
@@ -100,7 +100,6 @@ describe("node build", () => {
return Project.Service.of({
list: () => Effect.succeed([]),
update: () => Effect.die("not implemented"),
activate: () => Effect.void,
resolve: (directory) => Effect.succeed({ id: Project.ID.global, directory, canonical: directory }),
})
}),
-1
View File
@@ -13,7 +13,6 @@ export const globalProjectNode = makeGlobalNode({
return Project.Service.of({
list: () => Effect.succeed([]),
update: () => Effect.die("not implemented"),
activate: () => Effect.void,
resolve: (directory) => {
const project = { id: Project.ID.global, directory, canonical: directory }
return upsertProject(database.db, project).pipe(Effect.orDie, Effect.as(project))
-1
View File
@@ -14,7 +14,6 @@ const projectLayer = Layer.succeed(
Project.Service.of({
list: () => Effect.succeed([]),
update: () => Effect.die("not implemented"),
activate: () => Effect.void,
resolve: () =>
Effect.succeed({
id: Project.ID.make("project"),
+9 -35
View File
@@ -18,7 +18,7 @@ import { testEffect } from "./lib/effect"
const it = testEffect(AppNodeBuilder.build(LayerNode.group([Project.node, Database.node, Bus.node])))
describe("Project.list", () => {
it.effect("returns complete projects ordered by recent activity", () =>
it.effect("returns complete projects ordered by recent update", () =>
Effect.gen(function* () {
const db = (yield* Database.Service).db
const project = yield* Project.Service
@@ -35,7 +35,6 @@ describe("Project.list", () => {
sandboxes: [abs("/older/sandbox")],
time_created: 1,
time_updated: 1,
time_active: 4,
},
{
id: Project.ID.make("newer"),
@@ -44,12 +43,17 @@ describe("Project.list", () => {
time_created: 2,
time_updated: 2,
time_initialized: 3,
time_active: 3,
},
])
.run()
expect(yield* project.list()).toEqual([
{
id: Project.ID.make("newer"),
canonical: abs("/newer"),
time: { created: 2, updated: 2 },
sandboxes: [],
},
{
id: Project.ID.make("older"),
canonical: abs("/older"),
@@ -57,15 +61,9 @@ describe("Project.list", () => {
name: "Older",
icon: { color: "#000000" },
commands: { start: "bun dev" },
time: { created: 1, updated: 1, active: 4 },
time: { created: 1, updated: 1 },
sandboxes: [abs("/older/sandbox")],
},
{
id: Project.ID.make("newer"),
canonical: abs("/newer"),
time: { created: 2, updated: 2, active: 3 },
sandboxes: [],
},
])
}),
)
@@ -85,7 +83,6 @@ describe("Project.update", () => {
sandboxes: [],
time_created: 1,
time_updated: 1,
time_active: 1,
})
.run()
@@ -114,36 +111,13 @@ describe("Project.update", () => {
expect((yield* project.list())[0]).toEqual({
id,
canonical: abs("/update"),
time: { created: 1, updated: expect.any(Number), active: 1 },
time: { created: 1, updated: expect.any(Number) },
sandboxes: [],
})
}),
)
})
describe("Project.activate", () => {
it.effect("records activity without editing metadata time and throttles repeats", () =>
Effect.gen(function* () {
const db = (yield* Database.Service).db
const project = yield* Project.Service
const id = Project.ID.make("activate")
yield* db
.insert(ProjectTable)
.values({ id, worktree: abs("/activate"), sandboxes: [], time_created: 1, time_updated: 1, time_active: 1 })
.run()
yield* project.activate(id)
const first = (yield* project.list())[0]
expect(first?.time.updated).toBe(1)
expect(first?.time.active).toBeGreaterThan(1)
yield* db.update(ProjectTable).set({ time_active: 2, time_updated: 1 }).run()
yield* project.activate(id)
expect((yield* project.list())[0]?.time).toEqual({ created: 1, updated: 1, active: 2 })
}),
)
})
function remoteID(remote: string) {
return Project.ID.make(Hash.fast(`git-remote:${remote}`))
}
+1 -1
View File
@@ -1,7 +1,7 @@
import { describe, expect, test } from "bun:test"
import { State } from "@opencode/core/state"
import { Effect } from "effect"
import { FastCheck } from "effect/testing"
import FastCheck from "fast-check"
type Operation = { multiply: number; add: number }
type Value = { value: number; order: number[] }
+1 -1
View File
@@ -1042,7 +1042,7 @@ describe("Tool", () => {
value: Schema.Boolean.pipe(
Schema.decodeTo(Schema.String, {
decode: SchemaGetter.transform((value) => String(value)),
encode: SchemaGetter.transformOrFail((value) =>
encode: SchemaGetter.transformEffect((value) =>
value === "valid"
? Effect.succeed(true)
: Effect.fail(new SchemaIssue.InvalidValue({ message: "invalid output" }, value)),
+83
View File
@@ -67,6 +67,62 @@ test("Effect tool schemas use exact optional keys and flatten compatible constra
})
})
test.each([
{ name: "plain", input: Schema.Struct({}), metadata: {} },
{
name: "annotated",
input: Schema.Struct({}).annotate({ identifier: "Empty Input", description: "No parameters" }),
metadata: { description: "No parameters" },
},
])("empty $name Effect input structs describe callable object parameters", async ({ input, metadata }) => {
const tool: Info = {
name: "empty",
description: "Empty tool",
input,
output: input,
execute: (value) => Effect.succeed({ output: value }),
}
expect(definition(tool).inputSchema).toEqual({
...metadata,
type: "object",
properties: {},
additionalProperties: false,
})
expect(definition(tool).outputSchema).toEqual({ ...metadata, not: { type: "null" } })
expect(await Effect.runPromise(execute(tool, {}, context))).toMatchObject({ output: {} })
})
test("empty input normalization preserves explicit Effect overrides and raw JSON schemas", () => {
for (const override of [{ type: "object", additionalProperties: true }, { not: { type: "null" } }]) {
const tool: Info = {
name: "explicit",
description: "Explicit schema tool",
input: override,
execute: () => Effect.succeed({ content: "unused" }),
}
expect(definition(tool).inputSchema).toEqual(override)
const checked = Schema.Struct({}).check(Schema.makeFilter(() => true, { toJsonSchema: () => override }))
expect(definition({ ...tool, output: checked }).outputSchema).toEqual(
definition({ ...tool, input: checked }).inputSchema,
)
}
})
test("empty input normalization leaves nested empty structs unchanged", () => {
const tool: Info = {
name: "nested",
description: "Nested empty struct",
input: Schema.Struct({ value: Schema.Struct({}) }),
execute: () => Effect.succeed({ content: "unused" }),
}
expect(definition(tool).inputSchema).toEqual({
type: "object",
properties: { value: { not: { type: "null" } } },
required: ["value"],
additionalProperties: false,
})
})
test("Effect tool schemas inline named child schemas", () => {
const Child = Schema.Struct({ value: Schema.String }).annotate({ identifier: "Child" })
const tool: Info = {
@@ -106,6 +162,33 @@ test("Effect tool schemas resolve escaped definition names", () => {
expect(JSON.stringify(definition(tool).inputSchema)).not.toContain("$defs")
})
test.each(["Lookup Input", "café", "A/B~C% D#E"])(
"Effect tool schemas inline URI-encoded definition %s",
(identifier) => {
const child = Schema.Struct({ city: Schema.String }).annotate({ identifier })
const tool: Info = {
name: "encoded-reference",
description: "Encoded reference",
input: child,
output: Schema.Struct({ result: child }),
execute: () => Effect.succeed({ content: "unused" }),
}
const expected = {
type: "object",
properties: { city: { type: "string" } },
required: ["city"],
additionalProperties: false,
}
expect(definition(tool).inputSchema).toEqual(expected)
expect(definition(tool).outputSchema).toEqual({
type: "object",
properties: { result: expected },
required: ["result"],
additionalProperties: false,
})
},
)
test("portable schemas validate and describe typed tools", async () => {
const input = {
"~standard": {
@@ -1,19 +0,0 @@
import { describe, expect, test } from "bun:test"
import { ErrorSummary } from "../../src/util/error-summary"
describe("ErrorSummary", () => {
test("keeps the message and classification of each error in the cause chain", () => {
const root = Object.assign(new Error("connect ECONNREFUSED 127.0.0.1:443"), { code: "ECONNREFUSED", errno: -61 })
const error = new Error("Incompatible auth server: does not support dynamic client registration", { cause: root })
expect(ErrorSummary.from(error)).toEqual([
{ type: "Error", message: "Incompatible auth server: does not support dynamic client registration" },
{ type: "Error", message: "connect ECONNREFUSED 127.0.0.1:443", code: "ECONNREFUSED", errno: -61 },
])
})
test("omits the stack and empty messages", () => {
const summary = ErrorSummary.from(new Error(""))
expect(summary).toEqual([{ type: "Error" }])
expect(JSON.stringify(summary)).not.toContain("stack")
})
})
@@ -1,5 +1,5 @@
import { randomUUID } from "node:crypto"
import { Effect, FileSystem } from "effect"
import { ByteSize, Effect, FileSystem } from "effect"
import { nativeT } from "../native/translations"
export const MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024
@@ -43,7 +43,7 @@ export function readAttachment(filePath: string, maxBytes = MAX_ATTACHMENT_BYTES
const fs = yield* FileSystem.FileSystem
const file = yield* fs.open(filePath, { flag: "r" })
const info = yield* file.stat
if (info.size > FileSystem.Size(maxBytes))
if (info.size > ByteSize.bytes(maxBytes))
throw new Error(nativeT("desktop.picker.error.sizeLimit", { limit: MAX_ATTACHMENT_BYTES / 1024 / 1024 }))
const bytes = new Uint8Array(Number(info.size))
@@ -1,6 +1,7 @@
import { expect } from "bun:test"
import { NodeSocket } from "@effect/platform-node"
import { Deferred, Effect, Fiber, Layer, Queue, Scope, Exit } from "effect"
import { Socket } from "effect/unstable/socket"
import { testEffect } from "../../../../core/test/lib/effect"
import { createAskpass } from "./askpass"
@@ -12,16 +13,15 @@ const request = Effect.fn("test.askpass.request")(function* (
confirm = false,
) {
const socket = yield* NodeSocket.makeNet({ host: "127.0.0.1", port: Number(env.OPENCODE_SSH_ASKPASS_PORT) })
const write = yield* socket.writer
const writer = yield* socket.writer
const result = { text: "" }
yield* Effect.all(
[
socket
.runString((text) => {
result.text += text
})
.pipe(Effect.ignore),
write(JSON.stringify({ token: env.OPENCODE_SSH_ASKPASS_TOKEN, text, confirm }) + "\n").pipe(Effect.ignore),
Effect.gen(function* () {
const pull = yield* Socket.readerString(socket)
while (true) result.text += (yield* pull).join("")
}).pipe(Effect.ignore),
writer.write(JSON.stringify({ token: env.OPENCODE_SSH_ASKPASS_TOKEN, text, confirm }) + "\n").pipe(Effect.ignore),
],
{ concurrency: "unbounded" },
)
+18 -13
View File
@@ -1,5 +1,6 @@
import { NodeSocketServer } from "@effect/platform-node"
import { Deferred, Effect, Fiber, Schema, Semaphore } from "effect"
import { Socket } from "effect/unstable/socket"
import { randomUUID } from "node:crypto"
import { SshFailure } from "./command"
@@ -16,23 +17,27 @@ export const createAskpass = Effect.fn("Ssh.askpass")(function* (input: {
const pending = new Map<string, Deferred.Deferred<string>>()
const prompts = yield* Semaphore.make(1)
const server = yield* NodeSocketServer.make({ host: "127.0.0.1", port: 0 }).pipe(Effect.mapError(SshFailure.from))
if (server.address._tag !== "TcpAddress") return yield* Effect.fail(new SshFailure("connection"))
if (server.address._tag === "UnixPathAddress") return yield* Effect.fail(new SshFailure("connection"))
const serving = yield* server
.run((socket) =>
Effect.gen(function* () {
const request = yield* Deferred.make<string, SshFailure>()
const state = { buffer: "", received: false }
const reader = yield* socket
.runString((chunk) => {
if (state.received) return Effect.fail(new SshFailure("connection"))
state.buffer += chunk
if (state.buffer.length > 16_384) return Effect.fail(new SshFailure("connection"))
if (!state.buffer.includes("\n")) return Effect.void
state.received = true
return Deferred.succeed(request, state.buffer.trim())
})
.pipe(Effect.ensuring(Deferred.fail(request, new SshFailure("connection"))), Effect.forkScoped)
const reader = yield* Effect.gen(function* () {
const pull = yield* Socket.readerString(socket)
while (true) {
const chunks = yield* pull
for (const chunk of chunks) {
if (state.received) return yield* Effect.fail(new SshFailure("connection"))
state.buffer += chunk
if (state.buffer.length > 16_384) return yield* Effect.fail(new SshFailure("connection"))
if (!state.buffer.includes("\n")) continue
state.received = true
yield* Deferred.succeed(request, state.buffer.trim())
}
}
}).pipe(Effect.ensuring(Deferred.fail(request, new SshFailure("connection"))), Effect.forkScoped)
const message = yield* Deferred.await(request).pipe(Effect.flatMap(Schema.decodeUnknownEffect(Request)))
if (message.token !== token) return
@@ -49,8 +54,8 @@ export const createAskpass = Effect.fn("Ssh.askpass")(function* (input: {
)
yield* input.prompt({ id, text: message.text, confirm: message.confirm })
const value = yield* Deferred.await(response)
const write = yield* socket.writer
yield* write(JSON.stringify({ value }))
const writer = yield* socket.writer
yield* writer.write(JSON.stringify({ value }))
}).pipe(Effect.scoped),
)
.pipe(Effect.raceFirst(Fiber.join(reader).pipe(Effect.andThen(Effect.fail(new SshFailure("connection"))))))
@@ -1,5 +1,5 @@
import { expect } from "bun:test"
import { NodeServices, NodeSocketServer } from "@effect/platform-node"
import { NodeServices } from "@effect/platform-node"
import { Deferred, Effect, Fiber, FileSystem, Layer, Path, Stream } from "effect"
import { FetchHttpClient } from "effect/unstable/http"
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
@@ -228,17 +228,18 @@ it.live(
const path = yield* Path.Path
const config = path.join(yield* fs.makeTempDirectoryScoped({ prefix: "ssh-handshake-test-" }), "config")
yield* fs.writeFileString(config, "")
const connected = yield* Deferred.make<void>()
const closed = yield* Deferred.make<void>()
const server = yield* NodeSocketServer.make({ host: "127.0.0.1", port: 0 })
if (server.address._tag !== "TcpAddress") return yield* Effect.die("missing port")
yield* server
.run((socket) =>
socket
.run(() => Effect.void, { onOpen: Deferred.succeed(connected, undefined).pipe(Effect.asVoid) })
.pipe(Effect.ensuring(Deferred.succeed(closed, undefined)), Effect.ignore),
)
.pipe(Effect.forkScoped({ startImmediately: true }))
const connected = Promise.withResolvers<void>()
const closed = Promise.withResolvers<void>()
const server = Bun.listen({
hostname: "127.0.0.1",
port: 0,
socket: {
open: () => connected.resolve(),
data: () => {},
close: () => closed.resolve(),
},
})
yield* Effect.addFinalizer(() => Effect.sync(() => server.stop(true)))
const controller = yield* createSshController({
configs: [],
binary: "unused",
@@ -246,15 +247,16 @@ it.live(
save: () => Effect.die("must not save"),
})
yield* controller.start(
{ id: "fixture", target: `ssh -F ${quote(config)} -p ${server.address.port} 127.0.0.1`, name: "" },
{ id: "fixture", target: `ssh -F ${quote(config)} -p ${server.port} 127.0.0.1`, name: "" },
1,
)
yield* Deferred.await(connected)
const waiting = yield* controller.resolve("fixture").pipe(Effect.forkScoped)
yield* Effect.promise(() => connected.promise)
const waiting = yield* controller.resolve("fixture").pipe(Effect.forkScoped({ startImmediately: true }))
yield* controller.disconnect("fixture")
yield* Deferred.await(closed)
yield* Effect.promise(() => closed.promise)
expect(yield* Fiber.join(waiting)).toBeNull()
expect((yield* controller.state()).servers[0]?.stage).toBe("disconnected")
yield* controller.close
return undefined
}).pipe(Effect.timeout("10 seconds")),
)
+1 -1
View File
@@ -337,7 +337,7 @@ export const createSshController = Effect.fn("Ssh.controller")(function* (input:
const freePort = Effect.gen(function* () {
const server = yield* NodeSocketServer.make({ host: "127.0.0.1", port: 0 })
if (server.address._tag !== "TcpAddress") return yield* Effect.fail(new SshFailure("connection"))
if (server.address._tag === "UnixPathAddress") return yield* Effect.fail(new SshFailure("connection"))
return server.address.port
}).pipe(Effect.scoped)
+8 -16
View File
@@ -111,26 +111,18 @@ Real applications often select WebSocket URLs inside domain services. Effect rep
```ts
import { NodeSocket } from "@effect/platform-node"
import { it } from "@effect/vitest"
import { Deferred, Effect, Layer } from "effect"
import { Effect, Layer } from "effect"
import { Socket } from "effect/unstable/socket"
import { HttpRecorder } from "@opencode/http-recorder"
const roundTrip = Effect.fn("Echo.roundTrip")(function* (url: string, message: string) {
const socket = yield* Socket.makeWebSocket(url, { closeCodeIsError: () => false })
const write = yield* socket.writer
const echoed = yield* Deferred.make<string>()
yield* socket.runString(
(response) => {
return Deferred.succeed(echoed, response).pipe(
Effect.andThen(write(new Socket.CloseEvent(1000, "done"))),
Effect.orDie,
)
},
{ onOpen: write(message).pipe(Effect.orDie) },
)
return yield* Deferred.await(echoed)
const socket = yield* Socket.makeWebSocket(url)
const writer = yield* socket.writer
const pull = yield* Socket.readerString(socket)
yield* writer.write(message)
const [echoed] = yield* pull
yield* writer.write(new Socket.CloseEvent(1000, "done"))
return echoed
})
it.effect("round trips a message", () =>
+1 -1
View File
@@ -52,7 +52,7 @@
"typescript": "catalog:"
},
"dependencies": {
"@effect/platform-node-shared": "4.0.0-rc.112"
"@effect/platform-node-shared": "4.0.0-rc.115"
},
"peerDependencies": {
"effect": "catalog:"
+184 -161
View File
@@ -1,5 +1,5 @@
import { NodeFileSystem } from "@effect/platform-node-shared"
import { Deferred, Effect, Exit, FiberSet, Layer, Option, Ref, Scope, Semaphore } from "effect"
import { Deferred, Effect, Exit, Layer, Ref, Scope, Semaphore } from "effect"
import { Socket } from "effect/unstable/socket"
import { fileSystem, type Interface, Service } from "../cassette/store.js"
import type { SocketRecorderOptions } from "../options.js"
@@ -28,7 +28,7 @@ interface ActiveRecording {
interface PendingRecordings {
readonly promises: Set<Promise<void>>
readonly errors: Array<unknown>
readonly sockets: Set<globalThis.WebSocket>
readonly sockets: Set<Socket.WebSocketLike>
}
type Frame = string | Uint8Array
@@ -134,46 +134,6 @@ const assertEvent = (actual: WebSocketEvent, expected: WebSocketEvent | undefine
if (expected && comparable(actual, asJson) === comparable(expected, asJson)) return
throw new Error(`WebSocket event ${index + 1}: expected ${safeText(expected)}, received ${safeText(actual)}`)
})
const runHandler = <A, E, R>(handler: (value: A) => Effect.Effect<unknown, E, R> | void, value: A) =>
Effect.suspend(() => {
const result = handler(value)
return Effect.isEffect(result) ? Effect.asVoid(result) : Effect.void
})
const runReplay = <A, E, R>(
state: ActiveReplay,
handler: (value: A) => Effect.Effect<unknown, E, R> | void,
decode: (event: WebSocketEvent) => A,
onOpen: Effect.Effect<void> | undefined,
) =>
Effect.scoped(
Effect.gen(function* () {
const handlers = yield* FiberSet.make<unknown, E>()
const run = yield* FiberSet.runtime(handlers)<R>()
if (onOpen) yield* onOpen
const drive = Effect.gen(function* () {
while (true) {
const current = yield* Ref.get(state.progress)
const event = state.interaction.events[current.position]
if (!event) return
if (yield* Ref.get(state.closed))
return yield* Effect.die(
new Error(
`WebSocket closed with unconsumed events: used ${current.position} of ${state.interaction.events.length}`,
),
)
if (event.direction === "server") {
yield* Ref.set(state.progress, { position: current.position + 1, changed: yield* Deferred.make<void>() })
run(runHandler(handler, decode(event)))
continue
}
yield* Deferred.await(current.changed)
}
})
yield* drive.pipe(Effect.raceFirst(FiberSet.join(handlers)))
yield* FiberSet.awaitEmpty(handlers).pipe(Effect.raceFirst(FiberSet.join(handlers)))
}),
)
const makeRecordingSocket = (
upstream: Socket.Socket,
cassette: Interface,
@@ -185,71 +145,95 @@ const makeRecordingSocket = (
const active = yield* Ref.make<ActiveRecording | undefined>(undefined)
const writeLock = yield* Semaphore.make(1)
return Socket.make({
runRaw: (handler, runOptions) =>
Effect.gen(function* () {
const state: ActiveRecording = {
events: [],
eventLock: yield* Semaphore.make(1),
accepting: yield* Ref.make(true),
opened: false,
valid: true,
}
const occupied = yield* Ref.modify(active, (current) => [current !== undefined, current ?? state])
if (occupied) return yield* Effect.die("Concurrent runs of a recorded WebSocket are not supported")
yield* upstream
.runRaw(
(message) => {
if (!Ref.getUnsafe(state.accepting)) throw new Error("WebSocket received a frame after closing")
state.events.push(redactEvent(encodeEvent("server", message), redactor))
return handler(message)
},
{
...runOptions,
onOpen: Effect.gen(function* () {
state.opened = true
if (runOptions?.onOpen) yield* runOptions.onOpen
reader: Effect.gen(function* () {
const state: ActiveRecording = {
events: [],
eventLock: yield* Semaphore.make(1),
accepting: yield* Ref.make(true),
opened: false,
valid: true,
}
const occupied = yield* Ref.modify(active, (current) => [current !== undefined, current ?? state])
if (occupied) return yield* Effect.die("Concurrent runs of a recorded WebSocket are not supported")
yield* Effect.addFinalizer((exit) =>
writeLock.withPermit(
state.eventLock.withPermit(
Effect.gen(function* () {
yield* Ref.set(state.accepting, false)
yield* Ref.set(active, undefined)
if (!Exit.isSuccess(exit) || !state.opened || !state.valid) return
yield* cassette
.append(
name,
{
transport: "websocket",
events: [...state.events],
},
options.metadata,
)
.pipe(Effect.orDie)
}),
),
),
)
const reader = yield* upstream.reader
state.opened = true
return {
...reader,
pull: reader.pull.pipe(
Effect.tap((messages) =>
state.eventLock.withPermit(
Effect.sync(() => {
if (!Ref.getUnsafe(state.accepting)) throw new Error("WebSocket received a frame after closing")
state.events.push(...messages.map((message) => redactEvent(encodeEvent("server", message), redactor)))
}),
},
)
.pipe(
Effect.onExit((exit) =>
writeLock.withPermit(
state.eventLock.withPermit(
Effect.gen(function* () {
yield* Ref.set(state.accepting, false)
yield* Ref.set(active, undefined)
if (!Exit.isSuccess(exit) || !state.opened || !state.valid) return
yield* cassette
.append(
name,
{
transport: "websocket",
events: [...state.events],
},
options.metadata,
)
.pipe(Effect.orDie)
}),
),
),
),
)
}),
),
Effect.tapError((error) =>
Effect.sync(() => {
if (error.reason._tag !== "SocketCloseError") state.valid = false
}),
),
),
}
}),
writer: upstream.writer.pipe(
Effect.map(
(write) => (message) =>
Effect.map((writer) => {
const write: Socket.Writer["write"] = (message) =>
writeLock.withPermit(
Effect.gen(function* () {
if (Socket.isCloseEvent(message)) return yield* write(message)
if (Socket.isCloseEvent(message)) return yield* writer.write(message)
const state = yield* Ref.get(active)
if (!state || !(yield* Ref.get(state.accepting)))
return yield* Effect.die("WebSocket writer used without an active socket run")
const event = redactEvent(encodeEvent("client", message), redactor)
yield* state.eventLock.withPermit(Effect.sync(() => state.events.push(event)))
return yield* write(message).pipe(Effect.onError(() => Effect.sync(() => (state.valid = false))))
yield* state.eventLock.withPermit(
Effect.sync(() => state.events.push(redactEvent(encodeEvent("client", message), redactor))),
)
return yield* writer.write(message).pipe(Effect.onError(() => Effect.sync(() => (state.valid = false))))
}),
),
),
)
return {
write,
writeAll: (messages) =>
writeLock.withPermit(
Effect.gen(function* () {
const state = yield* Ref.get(active)
if (!state || !(yield* Ref.get(state.accepting)))
return yield* Effect.die("WebSocket writer used without an active socket run")
yield* state.eventLock.withPermit(
Effect.sync(() =>
state.events.push(
...messages.map((message) => redactEvent(encodeEvent("client", message), redactor)),
),
),
)
return yield* writer
.writeAll(messages)
.pipe(Effect.onError(() => Effect.sync(() => (state.valid = false))))
}),
),
}
}),
),
})
})
@@ -265,70 +249,109 @@ const makeReplaySocket = (
const active = yield* Ref.make<ActiveReplay | undefined>(undefined)
const runLock = yield* Semaphore.make(1)
return Socket.make({
runRaw: (handler, runOptions) =>
runLock
.withPermitsIfAvailable(1)(
Effect.gen(function* () {
const claimed = yield* replay
.claim((interaction) =>
interaction ? Effect.void : Effect.die("Missing recorded WebSocket interaction"),
)
.pipe(Effect.orDie)
const state = {
interaction: claimed.interaction,
progress: yield* Ref.make({ position: 0, changed: yield* Deferred.make<void>() }),
writeLock: yield* Semaphore.make(1),
closed: yield* Ref.make(false),
}
yield* Ref.set(active, state)
yield* runReplay(state, handler, decodeEvent, runOptions?.onOpen).pipe(
Effect.ensuring(Ref.set(active, undefined)),
)
}),
)
.pipe(
Effect.flatMap(
Option.match({
onNone: () => Effect.die("Concurrent runs of a replayed WebSocket are not supported"),
onSome: () => Effect.void,
}),
reader: Effect.gen(function* () {
if (!(yield* runLock.takeIfAvailable(1)))
return yield* Effect.die("Concurrent runs of a replayed WebSocket are not supported")
yield* Effect.addFinalizer(() =>
Effect.all([Ref.set(active, undefined), runLock.release(1)], { discard: true }),
)
const claimed = yield* replay
.claim((interaction) => (interaction ? Effect.void : Effect.die("Missing recorded WebSocket interaction")))
.pipe(Effect.orDie)
const state = {
interaction: claimed.interaction,
progress: yield* Ref.make({ position: 0, changed: yield* Deferred.make<void>() }),
writeLock: yield* Semaphore.make(1),
closed: yield* Ref.make(false),
}
yield* Ref.set(active, state)
const pull: Socket.Reader["pull"] = Effect.suspend(() =>
Effect.gen(function* () {
const current = yield* Ref.get(state.progress)
if (yield* Ref.get(state.closed))
return yield* Effect.fail(new Socket.SocketError({ reason: new Socket.SocketCloseError({ code: 1000 }) }))
const remaining = state.interaction.events.slice(current.position)
const client = remaining.findIndex((event) => event.direction === "client")
const messages = client === -1 ? remaining : remaining.slice(0, client)
if (messages.length > 0) {
yield* Ref.set(state.progress, {
position: current.position + messages.length,
changed: yield* Deferred.make<void>(),
})
return messages.map(decodeEvent) as [Frame, ...Array<Frame>]
}
if (current.position === state.interaction.events.length)
return yield* Effect.fail(new Socket.SocketError({ reason: new Socket.SocketCloseError({ code: 1000 }) }))
yield* Deferred.await(current.changed)
return yield* pull
}),
)
return { pull, upgrade: Socket.SocketUpgradeError.unsupported }
}),
writer: Effect.succeed({
write: (message) =>
Ref.get(active).pipe(
Effect.flatMap((state) =>
state
? state.writeLock.withPermit(
Effect.gen(function* () {
const current = yield* Ref.get(state.progress)
if (Socket.isCloseEvent(message)) {
yield* Ref.set(state.closed, true)
yield* Deferred.succeed(current.changed, undefined)
if (current.position === state.interaction.events.length) return
return yield* Effect.die(
new Error(
`WebSocket closed with unconsumed events: used ${current.position} of ${state.interaction.events.length}`,
),
)
}
const actual = redactEvent(encodeEvent("client", message), redactor)
yield* assertEvent(
actual,
state.interaction.events[current.position],
current.position,
options.compareClientMessagesAsJson === true,
)
yield* Ref.set(state.progress, {
position: current.position + 1,
changed: yield* Deferred.make<void>(),
})
yield* Deferred.succeed(current.changed, undefined)
}),
)
: Effect.die("WebSocket writer used without an active socket run"),
),
),
writer: Effect.succeed((message) =>
Ref.get(active).pipe(
Effect.flatMap((state) =>
state
? state.writeLock.withPermit(
Effect.gen(function* () {
const current = yield* Ref.get(state.progress)
if (Socket.isCloseEvent(message)) {
yield* Ref.set(state.closed, true)
yield* Deferred.succeed(current.changed, undefined)
if (current.position === state.interaction.events.length) return
return yield* Effect.die(
new Error(
`WebSocket closed with unconsumed events: used ${current.position} of ${state.interaction.events.length}`,
),
writeAll: (messages) =>
Effect.forEach(
messages,
(message) =>
Ref.get(active).pipe(
Effect.flatMap((state) =>
state
? state.writeLock.withPermit(
Effect.gen(function* () {
const current = yield* Ref.get(state.progress)
yield* assertEvent(
redactEvent(encodeEvent("client", message), redactor),
state.interaction.events[current.position],
current.position,
options.compareClientMessagesAsJson === true,
)
yield* Ref.set(state.progress, {
position: current.position + 1,
changed: yield* Deferred.make<void>(),
})
yield* Deferred.succeed(current.changed, undefined)
}),
)
}
const actual = redactEvent(encodeEvent("client", message), redactor)
yield* assertEvent(
actual,
state.interaction.events[current.position],
current.position,
options.compareClientMessagesAsJson === true,
)
yield* Ref.set(state.progress, {
position: current.position + 1,
changed: yield* Deferred.make<void>(),
})
yield* Deferred.succeed(current.changed, undefined)
}),
)
: Effect.die("WebSocket writer used without an active socket run"),
: Effect.die("WebSocket writer used without an active socket run"),
),
),
{ discard: true },
),
),
),
}),
})
})
@@ -399,13 +422,13 @@ const makeRecordingWebSocketConstructor = (
const onOpen = () => {
opened = true
}
const onMessage = (event: MessageEvent) => {
const onMessage = (event: Socket.WebSocketEvent) => {
appendEvent("server", event.data)
}
const onError = () => {
failed = true
}
const onClose = (event: CloseEvent) => {
const onClose = (event: Socket.WebSocketEvent) => {
native.removeEventListener("open", onOpen)
native.removeEventListener("message", onMessage)
native.removeEventListener("error", onError)
@@ -421,7 +444,7 @@ const makeRecordingWebSocketConstructor = (
sequence,
url: request.url,
protocols: requestedProtocols,
close: { code: event.code, reason: event.reason },
close: { code: event.code ?? 1006, reason: event.reason ?? "" },
},
events: [...events],
}
+104 -55
View File
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test"
import { Deferred, Effect, Exit, Fiber, Layer } from "effect"
import { Deferred, Effect, Exit, Fiber, FiberSet, Layer } from "effect"
import { Socket } from "effect/unstable/socket"
import { existsSync } from "node:fs"
import { HttpRecorder } from "../src"
@@ -7,10 +7,58 @@ import { layerSocketWithMode } from "../src/websocket/recorder"
import { failureText, readCassette, seedCassetteDirectory, tempDirectory, withEnvironment } from "./support"
const unavailableSocket = Socket.make({
runRaw: () => Effect.die(new Error("unexpected live WebSocket run")),
writer: Effect.succeed(() => Effect.die(new Error("unexpected live WebSocket write"))),
reader: Effect.die(new Error("unexpected live WebSocket run")),
writer: Effect.succeed({
write: () => Effect.die(new Error("unexpected live WebSocket write")),
writeAll: () => Effect.die(new Error("unexpected live WebSocket write")),
}),
})
const runRaw = <E, R>(
socket: Socket.Socket,
handler: (message: string | Uint8Array) => Effect.Effect<unknown, E, R> | void,
onOpen?: Effect.Effect<void, E, R>,
) =>
Effect.scoped(
Effect.gen(function* () {
const handlers = yield* FiberSet.make<unknown, E>()
const run = yield* FiberSet.runtime(handlers)<R>()
const reader = yield* socket.reader
if (onOpen) yield* onOpen
yield* Effect.gen(function* () {
while (true) {
const messages = yield* reader.pull
messages.forEach((message) =>
run(
Effect.suspend(() => {
const result = handler(message)
return Effect.isEffect(result) ? Effect.asVoid(result) : Effect.void
}),
),
)
}
}).pipe(
Effect.catchIf(
(error) => Socket.SocketError.is(error) && error.reason._tag === "SocketCloseError",
() => Effect.void,
),
Effect.raceFirst(FiberSet.join(handlers)),
)
yield* FiberSet.awaitEmpty(handlers).pipe(Effect.raceFirst(FiberSet.join(handlers)))
}),
)
const runString = <E, R>(
socket: Socket.Socket,
handler: (message: string) => Effect.Effect<unknown, E, R> | void,
onOpen?: Effect.Effect<void, E, R>,
) =>
runRaw(
socket,
(message) => handler(typeof message === "string" ? message : new TextDecoder().decode(message)),
onOpen,
)
class EchoWebSocket extends EventTarget {
readonly protocol = ""
readonly extensions = ""
@@ -53,12 +101,13 @@ describe("WebSocket", () => {
Effect.gen(function* () {
const socket = yield* Socket.makeWebSocket("wss://echo.example.test/one", {
protocols: ["echo.v1"],
closeCodeIsError: () => false,
})
const write = yield* socket.writer
yield* socket.runString(() => write(new Socket.CloseEvent(1000, "complete")).pipe(Effect.orDie), {
onOpen: write("hello").pipe(Effect.orDie),
})
const writer = yield* socket.writer
yield* runString(
socket,
() => writer.write(new Socket.CloseEvent(1000, "complete")).pipe(Effect.orDie),
writer.write("hello").pipe(Effect.orDie),
)
}).pipe(Effect.scoped, Effect.provide(recorder)),
),
)
@@ -141,17 +190,15 @@ describe("WebSocket", () => {
Effect.gen(function* () {
const socket = yield* Socket.makeWebSocket("wss://events.example.test/workspaces/one", {
protocols: ["events.v1"],
closeCodeIsError: () => false,
})
const write = yield* socket.writer
const writer = yield* socket.writer
const received: string[] = []
yield* socket.runString(
yield* runString(
socket,
(message) => {
received.push(message)
},
{
onOpen: write('{"type":"subscribe"}').pipe(Effect.orDie),
},
writer.write('{"type":"subscribe"}').pipe(Effect.orDie),
)
return received
}).pipe(Effect.scoped, Effect.provide(recorder)),
@@ -187,7 +234,7 @@ describe("WebSocket", () => {
const exit = await Effect.runPromise(
Effect.gen(function* () {
const socket = yield* Socket.makeWebSocket("wss://events.example.test/workspaces/two")
yield* socket.runString(() => {})
yield* runString<never, never>(socket, () => {})
}).pipe(Effect.scoped, Effect.exit, Effect.provide(recorder)),
)
@@ -200,23 +247,28 @@ describe("WebSocket", () => {
type: "response.completed",
token: "server-secret",
})
let sent = false
const upstream = Socket.make({
runRaw: (handler, options) =>
Effect.gen(function* () {
if (options?.onOpen) yield* options.onOpen
const result = handler(response)
if (Effect.isEffect(result)) yield* result
reader: Effect.succeed({
pull: Effect.suspend(() => {
if (sent) return Effect.fail(new Socket.SocketError({ reason: new Socket.SocketCloseError({ code: 1000 }) }))
sent = true
return Effect.succeed([response])
}),
writer: Effect.succeed(() => Effect.void),
upgrade: Socket.SocketUpgradeError.unsupported,
}),
writer: Effect.succeed({ write: () => Effect.void, writeAll: () => Effect.void }),
})
await Effect.runPromise(
Effect.gen(function* () {
const socket = yield* Socket.Socket
const write = yield* socket.writer
yield* socket.runRaw(() => {}, {
onOpen: write(JSON.stringify({ type: "response.create", token: "client-secret" })).pipe(Effect.orDie),
})
const writer = yield* socket.writer
yield* runRaw(
socket,
() => {},
writer.write(JSON.stringify({ type: "response.create", token: "client-secret" })).pipe(Effect.orDie),
)
}).pipe(
Effect.scoped,
Effect.provide(
@@ -279,14 +331,14 @@ describe("WebSocket", () => {
await Effect.runPromise(
Effect.gen(function* () {
const socket = yield* Socket.Socket
const write = yield* socket.writer
yield* socket.runRaw((message) =>
const writer = yield* socket.writer
yield* runRaw(socket, (message) =>
Effect.gen(function* () {
if (typeof message !== "string") return
received.push(message)
const event: unknown = JSON.parse(message)
if (typeof event !== "object" || event === null || !("type" in event)) return
if (event.type === "session.created") yield* write('{"prompt":"hello","type":"response.create"}')
if (event.type === "session.created") yield* writer.write('{"prompt":"hello","type":"response.create"}')
}),
)
}).pipe(
@@ -343,21 +395,21 @@ describe("WebSocket", () => {
await Effect.runPromise(
Effect.gen(function* () {
const socket = yield* Socket.Socket
const write = yield* socket.writer
yield* socket.runString((message) =>
const writer = yield* socket.writer
yield* runString(socket, (message) =>
Effect.gen(function* () {
received.push(message)
const event: unknown = JSON.parse(message)
if (typeof event !== "object" || event === null) return
if ("type" in event && event.type === "session.created") {
yield* write('{"prompt":"first","type":"response.create"}')
yield* writer.write('{"prompt":"first","type":"response.create"}')
return
}
if ("id" in event && event.id === "first") {
yield* write('{"prompt":"second","type":"response.create"}')
yield* writer.write('{"prompt":"second","type":"response.create"}')
return
}
yield* write(new Socket.CloseEvent(1000, "done"))
yield* writer.write(new Socket.CloseEvent(1000, "done"))
}),
)
}).pipe(
@@ -393,7 +445,7 @@ describe("WebSocket", () => {
Effect.gen(function* () {
const socket = yield* Socket.Socket
const second = yield* Deferred.make<void>()
yield* socket.runString((message) =>
yield* runString(socket, (message) =>
message === "first" ? Deferred.await(second) : Deferred.succeed(second, undefined),
)
}).pipe(
@@ -420,23 +472,21 @@ describe("WebSocket", () => {
const socket = yield* Socket.Socket
const started = yield* Deferred.make<void>()
const release = yield* Deferred.make<void>()
const first = yield* socket
.runString((message) =>
Effect.gen(function* () {
received.push(message)
yield* Deferred.succeed(started, undefined)
yield* Deferred.await(release)
}),
)
.pipe(Effect.forkChild)
const first = yield* runString(socket, (message) =>
Effect.gen(function* () {
received.push(message)
yield* Deferred.succeed(started, undefined)
yield* Deferred.await(release)
}),
).pipe(Effect.forkChild)
yield* Deferred.await(started)
const concurrent = yield* Effect.exit(socket.runString(() => Effect.void))
const concurrent = yield* Effect.exit(runString(socket, () => Effect.void))
expect(failureText(concurrent)).toContain("Concurrent runs")
yield* Deferred.succeed(release, undefined)
yield* Fiber.join(first)
yield* socket.runString((message) => Effect.sync(() => received.push(message)))
yield* runString(socket, (message) => Effect.sync(() => received.push(message)))
}).pipe(
Effect.scoped,
Effect.provide(
@@ -462,11 +512,9 @@ describe("WebSocket", () => {
const exit = await Effect.runPromise(
Effect.gen(function* () {
const socket = yield* Socket.Socket
const write = yield* socket.writer
const writer = yield* socket.writer
return yield* Effect.exit(
socket.runRaw(() => {}, {
onOpen: write(new Socket.CloseEvent(1000)).pipe(Effect.orDie),
}),
runRaw(socket, () => {}, writer.write(new Socket.CloseEvent(1000)).pipe(Effect.orDie)),
)
}).pipe(
Effect.scoped,
@@ -486,7 +534,7 @@ describe("WebSocket", () => {
const exit = await Effect.runPromise(
Effect.gen(function* () {
const socket = yield* Socket.Socket
return yield* Effect.exit(socket.runRaw(() => {}))
return yield* Effect.exit(runRaw<never, never>(socket, () => {}))
}).pipe(
Effect.scoped,
Effect.provide(
@@ -495,8 +543,8 @@ describe("WebSocket", () => {
Layer.succeed(
Socket.Socket,
Socket.make({
runRaw: () => Effect.die(new Error("connection failed")),
writer: Effect.succeed(() => Effect.void),
reader: Effect.die(new Error("connection failed")),
writer: Effect.succeed({ write: () => Effect.void, writeAll: () => Effect.void }),
}),
),
),
@@ -534,13 +582,14 @@ describe("WebSocket", () => {
await Effect.runPromise(
Effect.gen(function* () {
const socket = yield* Socket.Socket
const write = yield* socket.writer
const run = socket.runRaw(
const writer = yield* socket.writer
const run = runRaw(
socket,
(message) => {
if (typeof message === "string") throw new Error("Expected a binary WebSocket frame")
received.push([...message])
},
{ onOpen: write(new Uint8Array([1, 2])).pipe(Effect.orDie) },
writer.write(new Uint8Array([1, 2])).pipe(Effect.orDie),
)
yield* run
yield* run
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More