From c1fb0c2f938b2ed586089ccc08657beef5673258 Mon Sep 17 00:00:00 2001 From: Kevin Gibbons Date: Sun, 7 Dec 2025 18:59:22 -0800 Subject: [PATCH] add polyfill / test262 runner --- polyfill.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ run-test262.mjs | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 polyfill.js create mode 100644 run-test262.mjs diff --git a/polyfill.js b/polyfill.js new file mode 100644 index 0000000..8047ec2 --- /dev/null +++ b/polyfill.js @@ -0,0 +1,57 @@ +'use strict'; + +// this polyfill is spec-accurate, but not something you should actually use + +let join = { + join(separator) { + if (!this || typeof this !== 'object' && typeof this !== 'function') { + throw new TypeError('expected receiver to be an object'); + } + let sep; + if (separator === undefined) { + sep = ','; + } else { + try { + sep = `${separator}`; + } catch (e) { + try { + this.return(); + } catch { /* ignored */ } + throw e; + } + } + let next = this.next; + let R = ''; + let first = true; + while (true) { + let { done, value } = next.call(this); + if (done) { + return R; + } + if (first) { + first = false; + } else { + R = R + sep; + } + if (value !== undefined && value !== null) { + let S; + try { + S = `${value}`; + } catch (e) { + try { + this.return(); + } catch { /* ignored */ } + throw e; + } + R = R + S; + } + } + } +}.join; + +Object.defineProperty(Iterator.prototype, 'join', { + configurable: true, + writable: true, + enumerable: false, + value: join, +}); diff --git a/run-test262.mjs b/run-test262.mjs new file mode 100644 index 0000000..2c28398 --- /dev/null +++ b/run-test262.mjs @@ -0,0 +1,38 @@ +// assumes test262 is checked out in ../test262 + +import fs from 'node:fs'; +import vm from 'node:vm'; + +let testDir = '../test262/test/built-ins/Iterator'; +let files = fs.readdirSync(testDir, { recursive: true }); + +let harness = + fs.readFileSync('polyfill.js', 'utf8') + +[ + '../test262/harness/assert.js', + '../test262/harness/compareArray.js', + '../test262/harness/isConstructor.js', + '../test262/harness/iteratorZipUtils.js', + '../test262/harness/propertyHelper.js', + '../test262/harness/proxyTrapsHelper.js', + '../test262/harness/testTypedArray.js', + '../test262/harness/wellKnownIntrinsicObjects.js', +].map(x => fs.readFileSync(x, 'utf8')).join('\n') + ` +var $DETACHBUFFER = buff => buff.transfer(); +class Test262Error extends Error {} +`; + +for (let file of files) { + if (!file.endsWith('.js')) continue; + let basic = fs.readFileSync(testDir + '/' + file, 'utf8'); + if (!basic.includes('Iterator.prototype.join')) continue; + console.log(testDir + '/' + file); + let contents = harness + '\n(function(){ ' + basic + '})()'; + try { + vm.runInContext(contents, vm.createContext({ console })); + } catch (e) { + fs.writeFileSync('evaluated-test262.js', contents, 'utf8'); + console.log('evaluated-test262.js') + throw e; + } +}