Skip to content

Instantly share code, notes, and snippets.

@teppeis
Last active April 22, 2018 07:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save teppeis/c8a88f653cdd70ed3e3d6597ec1ee30c to your computer and use it in GitHub Desktop.
Save teppeis/c8a88f653cdd70ed3e3d6597ec1ee30c to your computer and use it in GitHub Desktop.
Testing Closure Compiler's polyfill with Test262 suite
'use strict';
const test262 = require('./test262_util');
test262.builtins('Array.prototype.copyWithin');
'use strict';
const fs = require('fs');
const os = require('os');
const path = require('path');
const vm = require('vm');
// NOTE: change these pathes for your environment
const test262Dir = path.join(os.homedir(), 'src/github.com/tc39/test262');
const closureRuntimeDir = path.join(os.homedir(), 'src/github.com/google/closure-compiler/src/com/google/javascript/jscomp/js');
const harnessAssert = readTest262Harness('assert.js');
const harnessSta = readTest262Harness('sta.js');
/**
* @param {string} target like 'Array.prototype.copyWithin' or 'Array.from'
*/
function builtins(target) {
// exp1m in closure. expm1 is correct.
const targetTestDir = path.join(test262Dir, 'test', 'built-ins', ...target.split('.').map(file => file.replace(/^exp1m$/, 'expm1')));
describe(target, () => {
const files = fs.readdirSync(targetTestDir);
files.sort().forEach(file => {
it(path.basename(file, '.js').replace(/-/g, ' '), () => {
runTest(target, path.join(targetTestDir, file));
});
});
});
}
/**
* @param {string} harness file name in 'test262/harsess' like 'assert.js'
* @return {string}
*/
function readTest262Harness(harness) {
return fs.readFileSync(path.join(test262Dir, 'harness', harness), 'utf8');
}
/**
* @param {string} polyfillFile relative path from src/com/google/javascript/jscomp/js like 'es6/array/fill.js'
* @return {string}
*/
function readClosureRuntime(polyfillFile) {
return fs.readFileSync(path.join(closureRuntimeDir, polyfillFile), 'utf8');
}
/**
* @param {string} polyfillPath relative path from src/com/google/javascript/jscomp/js w/o ext like 'es6/array/fill'
* @param {Array<string>=} polyfills
* @param {Map<string, string>=} cache
* @return {Array<string>}
*/
function loadPolyfill(polyfillPath, polyfills = [], cache = new Map()) {
let polyfill = cache.get(polyfillPath);
if (!polyfill) {
polyfill = readClosureRuntime(polyfillPath + '.js');
cache.set(polyfillPath, polyfill);
}
const regex = /^'require (.*)'/mg;
let match;
while ((match = regex.exec(polyfill)) !== null) {
const [, required] = match;
if (!cache.has(required)) {
loadPolyfill(required, polyfills, cache);
}
}
polyfills.push(polyfill);
return polyfills;
}
/**
* @param {string} testPath
* @return {Array<string>}
*/
function loadTest(testPath) {
const src = [];
const testSrc = fs.readFileSync(testPath, 'utf8');
const match = /^includes: \[(?:(?:, *)?([^,\]]*.js))+\]/m.exec(testSrc);
if (match) {
for (let i = 1; i < match.length; i++) {
src.push(readTest262Harness(match[i]));
}
}
src.push(testSrc);
return src;
}
/**
* @param {string} target
* @param {string} testPath
*/
function runTest(target, testPath) {
const targetPolyfillPath = path.join('es6',
...target.split('.').filter(item => item !== 'prototype').map(item => item.toLowerCase()));
const polyfills = loadPolyfill(targetPolyfillPath);
const testSrcList = loadTest(testPath);
const src = [`${target} = null;`, ...polyfills, harnessAssert, harnessSta, ...testSrcList];
vm.runInNewContext(src.join(';\n'), {console});
}
module.exports = {builtins};
@teppeis
Copy link
Author

teppeis commented Apr 22, 2018

How to run

  1. git clone https://github.com/tc39/test262 and https://github.com/google/closure-compiler
  2. Specify the cloned dirs as test262Dir and closureRuntimeDir in test262_util.js
  3. npx mocha array_copywithin_test.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment