mirror of https://github.com/tc39/test262.git
Converts test cases to proposed new canonical form
This commit is contained in:
parent
1f6f66cb19
commit
1558636929
|
@ -0,0 +1,429 @@
|
|||
|
||||
(function(global) {
|
||||
"use strict";
|
||||
|
||||
var t262 = global.t262;
|
||||
var platform = t262.platform;
|
||||
var regExp = platform.regExp;
|
||||
|
||||
var headerPattern = /(?:(?:\/\/.*)?\s*\n)*/;
|
||||
var captureCommentPattern = /\/\*\*?((?:\s|\S)*?)\*\/\s*\n/;
|
||||
var anyPattern = /(?:\s|\S)*/;
|
||||
var blanksPattern = /(?:\s|\n)*/;
|
||||
|
||||
// Should match anything
|
||||
var testEnvelopePattern =
|
||||
regExp('^(', headerPattern,
|
||||
')(?:', captureCommentPattern,
|
||||
')?(', anyPattern,
|
||||
')$');
|
||||
|
||||
var registerPattern =
|
||||
regExp('^(', anyPattern, '?)(',
|
||||
/ES5Harness\.registerTest\s*\(\s*\{/, anyPattern,
|
||||
/\}\s*\)/, ')',
|
||||
/\s*;?(?:\s|\n)*$/);
|
||||
|
||||
var captureFuncBodyPattern =
|
||||
regExp(/^function(?:\s+\w*)?\(\s*\)\s*\{/,
|
||||
'(', anyPattern, ')',
|
||||
/;?/, blanksPattern,
|
||||
/\}$/);
|
||||
|
||||
var captureExprBodyPattern =
|
||||
regExp(/^return\s+/,
|
||||
'(', anyPattern, '?)',
|
||||
/;$/);
|
||||
|
||||
var capturePredicatePattern =
|
||||
regExp(/^if\s+\((.*?)\)\s*\{/, blanksPattern,
|
||||
/return\s+true;?/, blanksPattern,
|
||||
/\}$/);
|
||||
|
||||
/**
|
||||
* Strip the left margin "*"s that are found in the body of a
|
||||
* multiline doc-comment like this one.
|
||||
*/
|
||||
function stripStars(text) {
|
||||
return text.replace(/\s*\n\s*\*\s?/g, '\n').trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the source of a test262 test case file into a JSON
|
||||
* envelope record.
|
||||
*
|
||||
* <p>The input can be in old sputnik or ietestcenter style, or in
|
||||
* the canonical test262 style. In all cases, we have an optional
|
||||
* header, an optional "/*" comment possibly containing properties
|
||||
* of the form<pre>
|
||||
* @propName: propValue;
|
||||
* </pre>which populate the test record. This is followed by the
|
||||
* rest of the text, which is the test itself. In the case of an
|
||||
* ietestcenter style test, this is followed by a call to
|
||||
* <code>ES5Harness\.registerTest</code> to register a test record.
|
||||
*/
|
||||
function parseTestEnvelope(src, name) {
|
||||
var envelope = { testRecord: {} };
|
||||
var envelopeMatch = testEnvelopePattern.exec(src);
|
||||
if (!envelopeMatch) {
|
||||
// Can't happen?
|
||||
throw new Error('unrecognized: ' + name);
|
||||
}
|
||||
envelope.header = envelopeMatch[1].trim();
|
||||
|
||||
if (envelopeMatch[2]) {
|
||||
var propTexts = envelopeMatch[2].split(/\s*\n\s*\*\s*@/);
|
||||
envelope.comment = stripStars(propTexts.shift()), // notice side effect
|
||||
propTexts.forEach(function(propText) {
|
||||
var propName = propText.match(/^\w+/)[0];
|
||||
var propVal = propText.substring(propName.length);
|
||||
var propMatch = /^:?([^;]*);?\s*$/.exec(propVal);
|
||||
if (propMatch) { propVal = propMatch[1]; }
|
||||
propVal = stripStars(propVal);
|
||||
if (propName in envelope.testRecord) {
|
||||
throw new Error('duplicate: ' + propName);
|
||||
}
|
||||
envelope.testRecord[propName] = propVal;
|
||||
});
|
||||
}
|
||||
envelope.rest = envelopeMatch[3]; // Do not trim
|
||||
|
||||
var registerMatch = registerPattern.exec(envelope.rest);
|
||||
if (registerMatch) {
|
||||
envelope.rest = registerMatch[1].trim();
|
||||
envelope.registerExpr = registerMatch[2].trim();
|
||||
} else if (envelope.rest.indexOf('ES5Harness.registerTest') >= 0) {
|
||||
print(' \n--header---\n|' + envelope.header +
|
||||
'|\n--rest-----\n|' + envelope.rest +
|
||||
'|\n--harness--\n|' + envelope.registerExpr +
|
||||
'|\n-----------\n');
|
||||
throw new Error('Malformed harness? ' + name);
|
||||
}
|
||||
return envelope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a function, return the source for an expression that, when
|
||||
* evaluated in the environment the function assumes, will behave
|
||||
* the same as calling that function in that environment.
|
||||
*/
|
||||
function expressionize(func) {
|
||||
var funcSrc = '' + func;
|
||||
var cfbMatch = captureFuncBodyPattern.exec(funcSrc);
|
||||
if (cfbMatch) {
|
||||
// Look for special cases
|
||||
var body = cfbMatch[1].trim();
|
||||
|
||||
var cebMatch = captureExprBodyPattern.exec(body);
|
||||
if (cebMatch) { return '(' + cebMatch[1].trim() + ')'; }
|
||||
|
||||
var cpMatch = capturePredicatePattern.exec(body);
|
||||
if (cpMatch) { return '(' + cpMatch[1].trim() + ')'; }
|
||||
|
||||
} else {
|
||||
// signal an error?
|
||||
}
|
||||
return '(' + funcSrc + ').call(this)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an ietestcenter style test, this <b>evaluates</b> the
|
||||
* registration expression in order to gather the test record.
|
||||
*/
|
||||
function gatherOne(envelope, name) {
|
||||
if (envelope.testRecord) {
|
||||
var propNames = Object.keys(envelope.testRecord);
|
||||
if (propNames.length >= 1) {
|
||||
// This need not be an error. It's just here so we notice the
|
||||
// first time it happens. This would happen if an
|
||||
// ietestcenter style test also had a comment with "@"
|
||||
// property definitions.
|
||||
throw new Error('unexpected in ' + name + ': ' + propNames);
|
||||
}
|
||||
}
|
||||
var testRecords = [];
|
||||
|
||||
// Evaluating!!!!
|
||||
platform.evalExprIn(envelope.registerExpr,
|
||||
{
|
||||
ES5Harness: {
|
||||
registerTest: function(testRecord) {
|
||||
testRecords.push(testRecord);
|
||||
}
|
||||
}
|
||||
},
|
||||
'forceNonStrict');
|
||||
|
||||
if (testRecords.length !== 1) {
|
||||
// We plan to lift this restriction in order to support test
|
||||
// generators.
|
||||
throw new Error('not singleton: ' + name);
|
||||
}
|
||||
var testRecord = testRecords[0];
|
||||
|
||||
if (typeof testRecord.test === 'function') {
|
||||
testRecord.test = envelope.rest +
|
||||
'assertTrue(' + expressionize(testRecord.test) + ');\n';
|
||||
}
|
||||
if (typeof testRecord.precondition === 'function') {
|
||||
var precondition = expressionize(testRecord.precondition);
|
||||
if (precondition === '(true)') {
|
||||
delete testRecord.precondition;
|
||||
} else {
|
||||
testRecord.precondition = precondition;
|
||||
}
|
||||
}
|
||||
|
||||
return testRecord;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalizes the properties of testRecord to be the canonical
|
||||
* test262 style properties, that will be assumed by the new test
|
||||
* runners.
|
||||
*/
|
||||
function normalizeProps(testRecord) {
|
||||
if (!testRecord.id && testRecord.name) {
|
||||
testRecord.id = testRecord.name;
|
||||
delete testRecord.name;
|
||||
}
|
||||
|
||||
if (!('strict_only' in testRecord) && testRecord.strict === 1) {
|
||||
testRecord.strict_only = '';
|
||||
delete testRecord.strict;
|
||||
}
|
||||
|
||||
if ('strict_mode_negative' in testRecord) {
|
||||
if (!('strict_only' in testRecord)) {
|
||||
testRecord.strict_only = '';
|
||||
}
|
||||
if (!'negative' in testRecord) {
|
||||
testRecord.negative = testRecord.strict_mode_negative;
|
||||
delete testRecord.strict_mode_negative;
|
||||
}
|
||||
}
|
||||
|
||||
if (!testRecord.negative && 'errortype' in testRecord) {
|
||||
testRecord.negative = testRecord.errortype;
|
||||
delete testRecord.errortype;
|
||||
}
|
||||
|
||||
if (!testRecord.description && testRecord.assertion) {
|
||||
testRecord.description = testRecord.assertion;
|
||||
delete testRecord.assertion;
|
||||
}
|
||||
if (!testRecord.comment && testRecord.assertion) {
|
||||
testRecord.comment = testRecord.assertion;
|
||||
delete testRecord.assertion;
|
||||
}
|
||||
};
|
||||
t262.normalizeProps = normalizeProps;
|
||||
|
||||
/**
|
||||
* Parses the source of a test262 test case file into a normalized
|
||||
* JSON test record.
|
||||
*/
|
||||
function parseTestRecord(path, name) {
|
||||
var nextPath = path.concat([name]);
|
||||
|
||||
var src = platform.read(nextPath);
|
||||
var testRecord;
|
||||
if (!src) { throw new Error('no src: ' + nextPath.join('/')); }
|
||||
var envelope = parseTestEnvelope(src, name);
|
||||
|
||||
if (envelope.registerExpr) {
|
||||
testRecord = gatherOne(envelope, name);
|
||||
} else {
|
||||
testRecord = envelope.testRecord;
|
||||
if (!testRecord.test) {
|
||||
testRecord.test = envelope.rest;
|
||||
}
|
||||
}
|
||||
testRecord.header = envelope.header;
|
||||
testRecord.comment = envelope.comment;
|
||||
|
||||
normalizeProps(testRecord);
|
||||
return testRecord;
|
||||
};
|
||||
t262.parseTestRecord = parseTestRecord;
|
||||
|
||||
// The known ones will be rendered first, and in this order.
|
||||
var KNOWN_PROPS = ['id', 'section', 'path', 'description',
|
||||
'strict_only', 'negative'];
|
||||
|
||||
/**
|
||||
* Turns the (assumed) normalized test record into its string form
|
||||
* in canonical test262 style.
|
||||
*
|
||||
* NOTE: This is currently destructive of testRecord. Easy to fix
|
||||
*if it becomes a problem.
|
||||
*/
|
||||
function formatTestRecord(testRecord) {
|
||||
var test = testRecord.test;
|
||||
delete testRecord.test;
|
||||
|
||||
function addProp(pname) {
|
||||
if (pname in testRecord) {
|
||||
result += ' * @' + pname;
|
||||
if (testRecord[pname]) {
|
||||
result += ': ' + testRecord[pname].replace(/\n/g, '\n * ');
|
||||
}
|
||||
result += ';\n';
|
||||
delete testRecord[pname];
|
||||
}
|
||||
}
|
||||
|
||||
var result = testRecord.header + '\n\n';
|
||||
delete testRecord.header;
|
||||
result += '/**\n';
|
||||
if (testRecord.comment) {
|
||||
result += ' * ' + testRecord.comment.replace(/\n/g, '\n * ') + '\n *\n';
|
||||
}
|
||||
delete testRecord.comment;
|
||||
KNOWN_PROPS.concat(['precondition']).forEach(addProp);
|
||||
Object.keys(testRecord).forEach(addProp);
|
||||
result += ' */\n\n' + test;
|
||||
return result;
|
||||
};
|
||||
t262.formatTestRecord = formatTestRecord;
|
||||
|
||||
/**
|
||||
* Reads the test case at pathStr and returns the source of that
|
||||
* test case converted to canonical test262 style.
|
||||
*/
|
||||
function convertTest(pathStr) {
|
||||
var path = platform.toPath(pathStr);
|
||||
var name = path.pop();
|
||||
var testRecord = parseTestRecord(path, name);
|
||||
var result = formatTestRecord(testRecord);
|
||||
return result;
|
||||
};
|
||||
t262.convertTest = convertTest;
|
||||
|
||||
var SRC_DIRS = [
|
||||
['test', 'suite', 'other'],
|
||||
['test', 'suite', 'sputnik', 'Conformance'],
|
||||
['test', 'suite', 'ietestcenter']
|
||||
];
|
||||
|
||||
var CONV_DIR = ['test', 'suite', 'converted'];
|
||||
|
||||
var OUT_DIR = ['website', 'resources', 'scripts', 'testcases2'];
|
||||
|
||||
var ME_PATH = platform.CONVERTER_PATH.concat('convert.js');
|
||||
|
||||
/**
|
||||
* Convert all the testcases found at inBase+relDir to test cases
|
||||
* in canonical test262 style, to be stored at corresponding
|
||||
* positions in outBase+relPath.
|
||||
*/
|
||||
function convertAll(inBase, outBase, relPath) {
|
||||
var inPath = inBase.concat(relPath);
|
||||
var outPath = outBase.concat(relPath);
|
||||
platform.mkdir(outPath);
|
||||
platform.ls(inPath).forEach(function(name) {
|
||||
var nextRelPath = relPath.concat([name]);
|
||||
if (platform.isDirectory(inBase.concat(nextRelPath))) {
|
||||
convertAll(inBase, outBase, nextRelPath);
|
||||
} else if (/\.js$/.test(name)) {
|
||||
var inFilePath = inPath.concat([name]);
|
||||
var outFilePath = outPath.concat([name]);
|
||||
platform.writeSpawn(
|
||||
[ME_PATH],
|
||||
't262.convertTest("' + platform.toPathStr(inFilePath) + '")',
|
||||
void 0,
|
||||
outFilePath);
|
||||
}
|
||||
});
|
||||
};
|
||||
t262.convertAll = convertAll;
|
||||
|
||||
/**
|
||||
* Do all the conversions (from sputnik style, ietestcenter style,
|
||||
* or other to canonical test262 style) matching relPath.
|
||||
*/
|
||||
function convert(opt_relPath) {
|
||||
SRC_DIRS.forEach(function(srcDir) {
|
||||
convertAll(srcDir, CONV_DIR, opt_relPath || []);
|
||||
});
|
||||
};
|
||||
t262.convert = convert;
|
||||
|
||||
/**
|
||||
* Reads all the test case records for the section corresponding to
|
||||
* the directory at pathStr, and return a JSON record for a test
|
||||
* case section, as would be uploaded to a browser-based test
|
||||
* runner.
|
||||
*/
|
||||
function buildSection(pathStr) {
|
||||
var path = platform.toPath(pathStr);
|
||||
if (!platform.isDirectory(path)) { throw new Error('not dir: ' + path); }
|
||||
|
||||
var jsFiles = platform.ls(path).filter(function(name) {
|
||||
return /\.js$/.test(name);
|
||||
});
|
||||
var testRecords = jsFiles.map(function(name) {
|
||||
var testRecord = parseTestRecord(path, name);
|
||||
|
||||
delete testRecord.header;
|
||||
delete testRecord.comment;
|
||||
return testRecord;
|
||||
});
|
||||
testRecords = testRecords.filter(function(testRecord) {
|
||||
return testRecord !== null;
|
||||
});
|
||||
return {
|
||||
testCollection: {
|
||||
name: path[path.length -1],
|
||||
numTests: testRecords.length,
|
||||
tests: testRecords
|
||||
}
|
||||
};
|
||||
};
|
||||
t262.buildSection = buildSection;
|
||||
|
||||
/**
|
||||
* Use the test cases at inBase+relPath to build the test
|
||||
* collection portion of the website, at outBase.
|
||||
*/
|
||||
function buildAll(inBase, outBase, relPath) {
|
||||
var inPath = inBase.concat(relPath);
|
||||
var hasJS = false;
|
||||
platform.ls(inPath).forEach(function(name) {
|
||||
var nextRelPath = relPath.concat([name]);
|
||||
if (platform.isDirectory(inBase.concat(nextRelPath))) {
|
||||
buildAll(inBase, outBase, nextRelPath);
|
||||
} else if (/\.js$/.test(name)) {
|
||||
hasJS = true;
|
||||
}
|
||||
});
|
||||
if (hasJS) {
|
||||
var name = relPath[relPath.length -1] + '.json';
|
||||
var outFilePath = outBase.concat([name]);
|
||||
platform.writeSpawn(
|
||||
[ME_PATH],
|
||||
't262.asJSONTxt(t262.buildSection("' +
|
||||
platform.toPathStr(inPath) + '"))',
|
||||
void 0,
|
||||
outFilePath);
|
||||
}
|
||||
};
|
||||
t262.buildAll = buildAll;
|
||||
|
||||
/**
|
||||
* Build those test case files for the website corresponding to the
|
||||
* test cases matching relPath.
|
||||
*
|
||||
* <p>Right now it's building from the pre-converted test
|
||||
* files. Once we switch over to converted as the maintained
|
||||
* sources, we should change this.
|
||||
*/
|
||||
function buildWebSite(opt_relPath) {
|
||||
SRC_DIRS.forEach(function(srcDir) {
|
||||
buildAll(srcDir, OUT_DIR, opt_relPath || []);
|
||||
});
|
||||
// buildAll(CONV_DIR, OUT_DIR, opt_relPath || []);
|
||||
};
|
||||
t262.buildWebSite = buildWebSite;
|
||||
|
||||
})(this);
|
|
@ -0,0 +1,275 @@
|
|||
|
||||
|
||||
/**
|
||||
* Each implementation of *Platform.js abstracts the underlying OS and JS
|
||||
* engine peculiarities.
|
||||
*
|
||||
* <p>The implementation here is specific to the v8 shell running on a
|
||||
* Posix platform.
|
||||
*/
|
||||
(function (global) {
|
||||
"use strict";
|
||||
|
||||
/////////////////// Development Switches /////////////////
|
||||
|
||||
var VERBOSE = true;
|
||||
|
||||
// Affects side effecting os operations,
|
||||
// currently only platform.writeSpawn and platform.mkdir.
|
||||
var DRY_RUN = false;
|
||||
|
||||
// When converting paths to path strings, should the pathstring be
|
||||
// relative to the TEST262_ROOT, or should it be relative to the
|
||||
// current working directory?
|
||||
var ABSOLUTE_PATHSTR = false;
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
global.t262 = global.t262 || {};
|
||||
|
||||
var platform = global.t262.platform = {};
|
||||
|
||||
/**
|
||||
* Appends a bunch of RegExps together into a single RegExp,
|
||||
* solving both the RegExp-one-liner problem and the doubled
|
||||
* backslash problem when composing literal string.
|
||||
*
|
||||
* <p>The arguments can be any mixture of RegExps and strings. The
|
||||
* strings are added as is without escaping -- BEWARE. If
|
||||
* arguments[0] is a RegExp, we use its flag on the resuting RegExp.
|
||||
*
|
||||
* <p>Not platform dependent, so does not really belong in this
|
||||
* file.
|
||||
*/
|
||||
function regExp(var_args) {
|
||||
var args = [].slice.call(arguments, 0);
|
||||
var reSrc = args.map(function(arg) {
|
||||
return (typeof arg === 'string') ? arg : arg.source;
|
||||
}).join('');
|
||||
var flags = '';
|
||||
if (typeof args[0] === 'object') {
|
||||
var parts = (''+args[0]).split('/');
|
||||
flags = parts[parts.length -1];
|
||||
}
|
||||
return new RegExp(reSrc, flags);
|
||||
}
|
||||
platform.regExp = regExp;
|
||||
|
||||
////////////////// Needed for building and running //////////////
|
||||
|
||||
try {
|
||||
read('tools/converter/v8PosixPlatform.js');
|
||||
} catch (err) {
|
||||
throw new Error('Must run in a test262 source root');
|
||||
}
|
||||
|
||||
var ABS_ROOT = os.system('pwd', ['-P']).trim().split('/');
|
||||
|
||||
var TEST262_ROOT = ABSOLUTE_PATHSTR ? ABS_ROOT : [];
|
||||
|
||||
var TEST262_ROOT_STR = TEST262_ROOT.join('/');
|
||||
|
||||
var CONVERTER_PATH = ['tools', 'converter'];
|
||||
platform.CONVERTER_PATH = CONVERTER_PATH;
|
||||
|
||||
var ME_PATH = CONVERTER_PATH.concat('v8PosixPlatform.js');
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function validatePath(path) {
|
||||
var pathStr = path.join('/');
|
||||
path.forEach(function(segment) {
|
||||
if (segment === '') {
|
||||
throw new Error('A path cannot have empty segment: ' + pathStr);
|
||||
}
|
||||
if (segment === '/') {
|
||||
throw new Error('Path insufficiently parsed: ' + pathStr);
|
||||
}
|
||||
if (segment === '..') {
|
||||
throw new Error('Cannot use "..": ' + pathStr);
|
||||
}
|
||||
});
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a path to a pathStr.
|
||||
*
|
||||
* A path is an array of filenames relative to TEST262_ROOT. A
|
||||
* pathStr is a (possibly fully qualified string) for referring to
|
||||
* that string on the current platform, according to the operations
|
||||
* in this *Platform.js file.
|
||||
*/
|
||||
function toPathStr(path) {
|
||||
validatePath(path);
|
||||
return TEST262_ROOT.concat(path).join('/');
|
||||
};
|
||||
platform.toPathStr = toPathStr;
|
||||
|
||||
/**
|
||||
* Returns the text found at path, with newlines normalized and
|
||||
* any initial BOM (Unicode Byte Order Mark) removed.
|
||||
*/
|
||||
platform.read = function(path) {
|
||||
var text = read(toPathStr(path)).
|
||||
replace(/\r\n/g, '\n').
|
||||
replace(/\r/g, '\n');
|
||||
if (text.charCodeAt(0) === 0xfeff) { return text.substring(1); }
|
||||
return text;
|
||||
};
|
||||
|
||||
/**
|
||||
* How one JavaScript script possibly spawns another and possibly
|
||||
* redirects its printed form to a chosen file (or resource).
|
||||
*
|
||||
* <p>For example, if !DRY_RUN, then<pre>
|
||||
* writeSpawn([], '+arguments[0] + +arguments[1]', ['3', '5'])
|
||||
* </pre>
|
||||
* should return the string "8", whether or not writeSpawn decides
|
||||
* to spawn.
|
||||
*
|
||||
* @param scriptPaths An array of path arrays of JavaScript source
|
||||
* files to be loaded into the spawned JS engine (in addition to
|
||||
* the spawning platform file) if we are indeed spawning.
|
||||
* @param opt_exprSrc An expression to be evaluated in an
|
||||
* environment in which "arguments" is bound to the list of strings
|
||||
* provided by opt_args. The result is the value of the expression
|
||||
* coerced to a string, unfortunately, as prepended by whatever
|
||||
* these scripts (if spawned) have already written to their
|
||||
* stdout. On platforms (like SES) where this can be a safely
|
||||
* confining evaluation, it should be. The implementation here is
|
||||
* not safe.
|
||||
* @param opt_args A list of strings to be bound to 'arguments'
|
||||
* both in opt_expr and in the possibly spawed scripts.
|
||||
* @param opt_targetPath A path array naming a file where the
|
||||
* result of opt_exprSrc should be written. On v8 currently, if
|
||||
* this is provided, then writeSpawn will spawn, since we have no
|
||||
* other way to implement this functionality. In the browser
|
||||
* context, the result is PUT (using XHR) to the target resource.
|
||||
* @param opt_spawn_required If truthy, forces spawning.
|
||||
* @returns If there is a target, then the null string. Otherwise,
|
||||
* the string result of evaluating opt_exprSrc.
|
||||
*/
|
||||
platform.writeSpawn = function(scriptPaths,
|
||||
opt_exprSrc,
|
||||
opt_args,
|
||||
opt_targetPath,
|
||||
opt_spawn_required,
|
||||
opt_forceNonStrict) {
|
||||
if (opt_exprSrc && !opt_targetPath && !opt_spawn_required) {
|
||||
var str = '(function(/*var_args*/) {';
|
||||
if (opt_forceNonStrict !== 'forceNonStrict') {
|
||||
str += '"use strict";';
|
||||
}
|
||||
str += ' return (' + opt_exprSrc + '); })';
|
||||
return ''+(1,eval)(str).apply(void 0, opt_args || []);
|
||||
}
|
||||
|
||||
var cmd = 'v8 ' + toPathStr(ME_PATH) + ' ';
|
||||
cmd += scriptPaths.map(toPathStr).join(' ');
|
||||
|
||||
if (opt_exprSrc) {
|
||||
cmd += ' -e ' + JSON.stringify('print(' + opt_exprSrc + ')');
|
||||
}
|
||||
if (opt_args) {
|
||||
cmd += ' -- ' + opt_args.map(JSON.stringify).join(' ');
|
||||
}
|
||||
if (opt_targetPath) {
|
||||
cmd += ' > ' + toPathStr(opt_targetPath);
|
||||
}
|
||||
if (VERBOSE || DRY_RUN) { print(cmd); }
|
||||
if (DRY_RUN) { return ''; }
|
||||
return os.system('bash', ['-c', cmd]);
|
||||
};
|
||||
|
||||
////////////////// Only needed for building /////////////////////
|
||||
|
||||
/**
|
||||
* Calls a non-strict indirect eval function on exprSrc.
|
||||
*
|
||||
* On platforms (like SES) where this can be a safely confining
|
||||
* evaluation, it should be. The implementation here is not safe.
|
||||
*/
|
||||
platform.evalExprIn = function(exprSrc, env, opt_forceNonStrict) {
|
||||
var varNames = Object.getOwnPropertyNames(env);
|
||||
var str = '(function(' + varNames.join(',') + ') {';
|
||||
if (opt_forceNonStrict !== 'forceNonStrict') {
|
||||
str += '"use strict";';
|
||||
}
|
||||
str += ' return (' + exprSrc + '); })';
|
||||
return (1,eval)(str).apply(void 0, varNames.map(function(varName) {
|
||||
return env[varName];
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a pathStr to a path.
|
||||
*
|
||||
* See toPathStr.
|
||||
*/
|
||||
function toPath(pathStr) {
|
||||
if (pathStr[0] === '/') {
|
||||
if (pathStr.indexOf(TEST262_ROOT_STR + '/') !== 0) {
|
||||
throw new Error('"' + pathStr + '" must start with "' +
|
||||
TEST262_ROOT_STR + '/"');
|
||||
}
|
||||
pathStr = pathStr.substring(TEST262_ROOT_STR.length + 1);
|
||||
}
|
||||
return validatePath(pathStr.split('/'));
|
||||
}
|
||||
platform.toPath = toPath;
|
||||
|
||||
/**
|
||||
* Does path name a directory?
|
||||
*/
|
||||
platform.isDirectory = function(path) {
|
||||
var fileOut = os.system('file', [toPathStr(path)]);
|
||||
var fileMatch = fileOut.match(/:\s*([^:]*)\s*$/);
|
||||
if (!fileMatch) { return null; }
|
||||
var fileType = fileMatch[1].trim();
|
||||
return fileType === 'directory';
|
||||
};
|
||||
|
||||
/**
|
||||
* A list of the filenames found in path, which must name a
|
||||
* directory.
|
||||
*/
|
||||
platform.ls = function(path) {
|
||||
var pathStr = toPathStr(path);
|
||||
var lines = os.system('ls', [pathStr]).trim();
|
||||
if (lines === '') { return []; }
|
||||
return lines.split('\n');
|
||||
};
|
||||
|
||||
/**
|
||||
* Emits the jsonRecord serialized as JSON, either compactly or
|
||||
* readably according to VERBOSE.
|
||||
*/
|
||||
function asJSONTxt(jsonRecord) {
|
||||
if (VERBOSE) {
|
||||
return JSON.stringify(jsonRecord, void 0, ' ');
|
||||
} else {
|
||||
return JSON.stringify(jsonRecord);
|
||||
}
|
||||
}
|
||||
global.t262.asJSONTxt = platform.asJSONTxt = asJSONTxt;
|
||||
|
||||
platform.mkdir = function(path) {
|
||||
var pathStr = toPathStr(path);
|
||||
if (DRY_RUN) {
|
||||
print('mkdir ' + pathStr);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
os.mkdirp(pathStr);
|
||||
} catch (err) {
|
||||
print('***could not mkdir: ' + pathStr);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////// Only needed for running //////////////////////
|
||||
|
||||
|
||||
})(this);
|
Loading…
Reference in New Issue