Now generating the format David Fugate and I agreed on this

morning. The rewrite of "function testcase()..." now puts the
assertTrue at the bottom. Preconditions, names, and ids are
removed. And the path in the file is ignored, and is instead set
accurately according to where the file is found.
This commit is contained in:
Mark Miller 2011-09-07 21:42:49 -07:00
parent 57c450002d
commit ca417c93dc
4 changed files with 270 additions and 153 deletions

View File

@ -1,4 +1,4 @@
/// Copyright (c) 2009 Microsoft Corporation /// Copyright (c) 2009 Microsoft Corporation
/// ///
/// Redistribution and use in source and binary forms, with or without modification, are permitted provided /// Redistribution and use in source and binary forms, with or without modification, are permitted provided
/// that the following conditions are met: /// that the following conditions are met:
@ -52,7 +52,7 @@ function BrowserRunner() {
if(currentTest.error instanceof SputnikError) { if(currentTest.error instanceof SputnikError) {
currentTest.error = currentTest.message; currentTest.error = currentTest.message;
} else { } else {
currentTest.error = currentTest.error.name + ": " + currentTest.error.message currentTest.error = currentTest.error.name + ": " + currentTest.error.message;
} }
} }
@ -112,8 +112,8 @@ function BrowserRunner() {
$.ajax({ $.ajax({
async: false, async: false,
url: 'resources/scripts/global/' + include, url: 'resources/scripts/global/' + include,
success: function(s) { scriptCache[include] = s } success: function(s) { scriptCache[include] = s; }
}) });
} }
// Finally, write the required script to the window. // Finally, write the required script to the window.
@ -182,7 +182,7 @@ function BrowserRunner() {
} }
doc.writeln("<script type='text/javascript'>testFinished();</script>"); doc.writeln("<script type='text/javascript'>testFinished();</script>");
doc.close(); doc.close();
} };
} }
/* Loads tests from the sections specified in testcaseslist.json. /* Loads tests from the sections specified in testcaseslist.json.
@ -244,7 +244,7 @@ function TestLoader() {
testGroups[i] = { testGroups[i] = {
path: testSuite[i], path: testSuite[i],
tests: [] tests: []
} };
} }
loader.onInitialized(loader.totalTests, loader.version, loader.date); loader.onInitialized(loader.totalTests, loader.version, loader.date);
getNextXML(); getNextXML();
@ -271,13 +271,13 @@ function TestLoader() {
// We're done. // We're done.
loader.onTestsExhausted(); loader.onTestsExhausted();
} }
} };
/* Start over at the beginning */ /* Start over at the beginning */
this.reset = function() { this.reset = function() {
currentTestIndex = 0; currentTestIndex = 0;
testGroupIndex = 0; testGroupIndex = 0;
} };
} }
/* Controls test generation and running, and sends results to the presenter. */ /* Controls test generation and running, and sends results to the presenter. */
@ -294,22 +294,22 @@ function Controller() {
if(state === 'running') if(state === 'running')
setTimeout(loader.getNextTest, 10); setTimeout(loader.getNextTest, 10);
} };
loader.onInitialized = function(totalTests, version, date) { loader.onInitialized = function(totalTests, version, date) {
presenter.setVersion(version); presenter.setVersion(version);
presenter.setDate(date); presenter.setDate(date);
presenter.setTotalTests(totalTests); presenter.setTotalTests(totalTests);
} };
loader.onLoadingNextSection = function(path) { loader.onLoadingNextSection = function(path) {
presenter.updateStatus("Loading: " + path); presenter.updateStatus("Loading: " + path);
} };
loader.onTestReady = function(id, test) { loader.onTestReady = function(id, test) {
presenter.updateStatus("Executing Test: " + id); presenter.updateStatus("Executing Test: " + id);
runner.run(id, test); runner.run(id, test);
} };
loader.onTestsExhausted = function() { loader.onTestsExhausted = function() {
state = 'stopped'; state = 'stopped';
@ -317,27 +317,27 @@ function Controller() {
elapsed = elapsed/(1000*60); //minutes elapsed = elapsed/(1000*60); //minutes
elapsed = elapsed.toFixed(1); elapsed = elapsed.toFixed(1);
presenter.finished(elapsed); presenter.finished(elapsed);
} };
this.start = function() { this.start = function() {
state = 'running'; state = 'running';
startTime = new Date(); startTime = new Date();
loader.getNextTest(); loader.getNextTest();
presenter.started(); presenter.started();
} };
this.pause = function() { this.pause = function() {
elapsed += new Date() - startTime; elapsed += new Date() - startTime;
state = 'paused'; state = 'paused';
presenter.paused(); presenter.paused();
} };
this.reset = function() { this.reset = function() {
startTime = new Date(); startTime = new Date();
elapsed = 0; elapsed = 0;
loader.reset(); loader.reset();
presenter.reset(); presenter.reset();
} };
this.toggle = function() { this.toggle = function() {
if(state === 'running') { if(state === 'running') {
@ -345,16 +345,16 @@ function Controller() {
} else { } else {
controller.start(); controller.start();
} }
} };
} }
var controller = new Controller() var controller = new Controller();
/* Helper function which shows if we're in the 'debug' mode of the Test262 site. /* Helper function which shows if we're in the 'debug' mode of the Test262 site.
This mode is only useful for debugging issues with the test harness and This mode is only useful for debugging issues with the test harness and
website. */ website. */
function isSiteDebugMode() { function isSiteDebugMode() {
var str=window.location.href.substring(window.location.href.indexOf("?")+1) var str=window.location.href.substring(window.location.href.indexOf("?")+1);
if(str.indexOf("sitedebug") > -1) { if(str.indexOf("sitedebug") > -1) {
return true; return true;
} }

View File

@ -139,7 +139,7 @@ namespace Microsoft.Sputnik.Interop.ParserEngine
} }
FileStream fs = new FileStream(destination.Remove(destination.LastIndexOf("\\")) + globalScopeFileName, FileMode.Create, FileAccess.Write); FileStream fs = new FileStream(destination.Remove(destination.LastIndexOf("\\")) + globalScopeFileName, FileMode.Create, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs); StreamWriter sw = new StreamWriter(fs);
sw.Write("this.GlobalScopeTests = this.GlobalScopeTests || new Array();\n"); sw.Write("this.GlobalScopeTests = this.GlobalScopeTests || {};\n");
sw.Flush(); sw.Flush();
sw.Close(); sw.Close();
fs.Close(); fs.Close();

View File

@ -8,6 +8,10 @@
var t262 = global.t262; var t262 = global.t262;
var platform = t262.platform; var platform = t262.platform;
var regExp = platform.regExp; var regExp = platform.regExp;
var toRelPathStr = platform.toRelPathStr;
var toPathStr = platform.toPathStr;
var toRelPath = platform.toRelPath;
var toPath = platform.toPath;
var headerPattern = /(?:(?:\/\/.*)?\s*\n)*/; var headerPattern = /(?:(?:\/\/.*)?\s*\n)*/;
var captureCommentPattern = /\/\*\*?((?:\s|\S)*?)\*\/\s*\n/; var captureCommentPattern = /\/\*\*?((?:\s|\S)*?)\*\/\s*\n/;
@ -27,8 +31,9 @@
/\}\s*\)/, ')', /\}\s*\)/, ')',
/\s*;?(?:\s|\n)*$/); /\s*;?(?:\s|\n)*$/);
var captureFuncBodyPattern = // Matches a named function. Captures both the name and the body.
regExp(/^function(?:\s+\w*)?\(\s*\)\s*\{/, var captureFuncNameBodyPattern =
regExp(/^function\s+(\w*)\(\s*\)\s*\{/,
'(', anyPattern, ')', '(', anyPattern, ')',
/;?/, blanksPattern, /;?/, blanksPattern,
/\}$/); /\}$/);
@ -80,8 +85,10 @@
propTexts.forEach(function(propText) { propTexts.forEach(function(propText) {
var propName = propText.match(/^\w+/)[0]; var propName = propText.match(/^\w+/)[0];
var propVal = propText.substring(propName.length); var propVal = propText.substring(propName.length);
var propMatch = /^:?([^;]*);?\s*$/.exec(propVal); // strip optional initial colon or final semicolon.
if (propMatch) { propVal = propMatch[1]; } // The initial colon is only stripped if it comes immediately
// after the identifier with no intervening whitespace.
propVal = propVal.replace(/^:\s*/, '').replace(/;\s*$/, '');
propVal = stripStars(propVal); propVal = stripStars(propVal);
if (propName in envelope.testRecord) { if (propName in envelope.testRecord) {
throw new Error('duplicate: ' + propName); throw new Error('duplicate: ' + propName);
@ -106,27 +113,49 @@
} }
/** /**
* Given a function, return the source for an expression that, when * Given a function that indicates success by returning a truthy
* evaluated in the environment the function assumes, will behave * value, return the source for a Program that, when evaluated in
* the same as calling that function in that environment. * the environment the function assumes, will behave the same as
* calling that function in that environment and asserting the
* truthiness of the result.
*
* <p>Programs do not conveniently return any value, even their
* completion value, so Programs in canonical test262 style instead
* indicate success simply by completing normally, i.e., without
* throwing anything. The convertion assumes a one argument
* <code>assertTrue</code> function which throws an indication of
* test failure iff given a falsy argument.
*
* <p>Unless it specifies otherwise, the Program source may be
* executed strict and/or non-strict, and it may be exeuted within
* the try block of a try/catch or try/catch finally, i.e., as a
* Block rather than as a Program.
*/ */
function expressionize(func) { function functionToProgramSrc(func) {
var funcSrc = '' + func; var funcSrc = '' + func;
var cfbMatch = captureFuncBodyPattern.exec(funcSrc); var cfnbMatch = captureFuncNameBodyPattern.exec(funcSrc);
if (cfbMatch) { if (!cfnbMatch) {
// Look for special cases throw new Error('Could not recognize: "' + funcSrc + '"');
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)'; var name = cfnbMatch[1].trim();
var body = cfnbMatch[2].trim();
// Look for special cases
var cebMatch = captureExprBodyPattern.exec(body);
if (cebMatch) {
return 'assertTrue(' + cebMatch[1].trim() + ');';
}
var cpMatch = capturePredicatePattern.exec(body);
if (cpMatch) {
return 'assertTrue(' + cpMatch[1].trim() + ');';
}
// General case
return funcSrc + '\n' +
'assertTrue(' + name + '.call(this));';
} }
/** /**
@ -158,27 +187,25 @@
'forceNonStrict'); 'forceNonStrict');
if (testRecords.length !== 1) { if (testRecords.length !== 1) {
// We plan to lift this restriction in order to support test // We may lift this restriction in order to support test
// generators. // generators.
throw new Error('not singleton: ' + name); throw new Error('not singleton: ' + name);
} }
var testRecord = testRecords[0]; var testRecord = testRecords[0];
if (typeof testRecord.test === 'function') { if (typeof testRecord.test === 'function') {
testRecord.test = envelope.rest + testRecord.test = envelope.rest + '\n' +
'assertTrue(' + expressionize(testRecord.test) + ');\n'; functionToProgramSrc(testRecord.test);
} }
if (typeof testRecord.precondition === 'function') { if ('precondition' in testRecord) {
var precondition = expressionize(testRecord.precondition); // Only ietestcenter tests currently have preconditions, and they
if (precondition === '(true)') { // plan to drop them. So canonical test262 style omits
delete testRecord.precondition; // them.
} else { delete testRecord.precondition;
testRecord.precondition = precondition;
}
} }
return testRecord; return testRecord;
}; }
/** /**
* Normalizes the properties of testRecord to be the canonical * Normalizes the properties of testRecord to be the canonical
@ -186,11 +213,6 @@
* runners. * runners.
*/ */
function normalizeProps(testRecord) { function normalizeProps(testRecord) {
if (!testRecord.id && testRecord.name) {
testRecord.id = testRecord.name;
delete testRecord.name;
}
if (!('strict_only' in testRecord) && testRecord.strict === 1) { if (!('strict_only' in testRecord) && testRecord.strict === 1) {
testRecord.strict_only = ''; testRecord.strict_only = '';
delete testRecord.strict; delete testRecord.strict;
@ -206,6 +228,8 @@
} }
} }
// Note that testRecord.negative is falsy whether negative is
// absent or empty.
if (!testRecord.negative && 'errortype' in testRecord) { if (!testRecord.negative && 'errortype' in testRecord) {
testRecord.negative = testRecord.errortype; testRecord.negative = testRecord.errortype;
delete testRecord.errortype; delete testRecord.errortype;
@ -219,19 +243,22 @@
testRecord.comment = testRecord.assertion; testRecord.comment = testRecord.assertion;
delete testRecord.assertion; delete testRecord.assertion;
} }
}; }
t262.normalizeProps = normalizeProps; t262.normalizeProps = normalizeProps;
/** /**
* Parses the source of a test262 test case file into a normalized * Parses the source of a test262 test case file into a normalized
* JSON test record. * JSON test record.
*/ */
function parseTestRecord(path, name) { function parseTestRecord(inBase, relPath, name) {
var nextPath = path.concat([name]); var nextRelPath = relPath.concat([name]);
var nextPath = inBase.concat(nextRelPath);
var src = platform.read(nextPath); var src = platform.read(nextPath);
var testRecord; var testRecord;
if (!src) { throw new Error('no src: ' + nextPath.join('/')); } if (!src) {
throw new Error('no src: ' + toPathStr(nextPath));
}
var envelope = parseTestEnvelope(src, name); var envelope = parseTestEnvelope(src, name);
if (envelope.registerExpr) { if (envelope.registerExpr) {
@ -242,16 +269,19 @@
testRecord.test = envelope.rest; testRecord.test = envelope.rest;
} }
} }
delete testRecord.id;
delete testRecord.name;
testRecord.path = toRelPathStr(nextRelPath);
testRecord.header = envelope.header; testRecord.header = envelope.header;
testRecord.comment = envelope.comment; testRecord.comment = envelope.comment;
normalizeProps(testRecord); normalizeProps(testRecord);
return testRecord; return testRecord;
}; }
t262.parseTestRecord = parseTestRecord; t262.parseTestRecord = parseTestRecord;
// The known ones will be rendered first, and in this order. // The known ones will be rendered first, and in this order.
var KNOWN_PROPS = ['id', 'section', 'path', 'description', var KNOWN_PROPS = ['section', 'path', 'description',
'strict_only', 'negative']; 'strict_only', 'negative'];
/** /**
@ -283,30 +313,31 @@
result += ' * ' + testRecord.comment.replace(/\n/g, '\n * ') + '\n *\n'; result += ' * ' + testRecord.comment.replace(/\n/g, '\n * ') + '\n *\n';
} }
delete testRecord.comment; delete testRecord.comment;
KNOWN_PROPS.concat(['precondition']).forEach(addProp); KNOWN_PROPS.forEach(addProp);
Object.keys(testRecord).forEach(addProp); Object.keys(testRecord).forEach(addProp);
result += ' */\n\n' + test; result += ' */\n\n' + test;
return result; return result;
}; }
t262.formatTestRecord = formatTestRecord; t262.formatTestRecord = formatTestRecord;
/** /**
* Reads the test case at pathStr and returns the source of that * Reads the test case at pathStr and returns the source of that
* test case converted to canonical test262 style. * test case converted to canonical test262 style.
*/ */
function convertTest(pathStr) { function convertTest(inBaseStr, relPathStr) {
var path = platform.toPath(pathStr); var inBase = toPath(inBaseStr);
var name = path.pop(); var relPath = platform.toRelPath(relPathStr);
var testRecord = parseTestRecord(path, name); var name = relPath.pop();
var testRecord = parseTestRecord(inBase, relPath, name);
var result = formatTestRecord(testRecord); var result = formatTestRecord(testRecord);
return result; return result;
}; }
t262.convertTest = convertTest; t262.convertTest = convertTest;
var SRC_DIRS = [ var SRC_DIRS = [
['test', 'suite', 'other'], ['test', 'suite', 'other'],
['test', 'suite', 'sputnik', 'Conformance'], ['test', 'suite', 'ietestcenter'],
['test', 'suite', 'ietestcenter'] ['test', 'suite', 'sputnik', 'Conformance']
]; ];
var CONV_DIR = ['test', 'suite', 'converted']; var CONV_DIR = ['test', 'suite', 'converted'];
@ -315,6 +346,8 @@
var ME_PATH = platform.CONVERTER_PATH.concat('convert.js'); var ME_PATH = platform.CONVERTER_PATH.concat('convert.js');
var writeSpawnFailures = [];
/** /**
* Convert all the testcases found at inBase+relDir to test cases * Convert all the testcases found at inBase+relDir to test cases
* in canonical test262 style, to be stored at corresponding * in canonical test262 style, to be stored at corresponding
@ -329,27 +362,43 @@
if (platform.isDirectory(inBase.concat(nextRelPath))) { if (platform.isDirectory(inBase.concat(nextRelPath))) {
convertAll(inBase, outBase, nextRelPath); convertAll(inBase, outBase, nextRelPath);
} else if (/\.js$/.test(name)) { } else if (/\.js$/.test(name)) {
var inFilePath = inPath.concat([name]);
var outFilePath = outPath.concat([name]); var outFilePath = outPath.concat([name]);
platform.writeSpawn( try {
[ME_PATH], platform.writeSpawn(
't262.convertTest("' + platform.toPathStr(inFilePath) + '")', [ME_PATH],
void 0, 't262.convertTest("' + toPathStr(inBase) +
outFilePath); '", "' + toRelPathStr(nextRelPath) + '")',
void 0,
outFilePath);
} catch (err) {
writeSpawnFailures.push({
error: err,
relPath: relPath
});
}
} }
}); });
}; }
t262.convertAll = convertAll; t262.convertAll = convertAll;
/** /**
* Do all the conversions (from sputnik style, ietestcenter style, * Do all the conversions (from sputnik style, ietestcenter style,
* or other to canonical test262 style) matching relPath. * or other to canonical test262 style) matching relPath.
*/ */
function convert(opt_relPath) { function convert(opt_relPathStr) {
var relPath = opt_relPathStr ? toRelPath(opt_relPathStr) : [];
writeSpawnFailures = [];
SRC_DIRS.forEach(function(srcDir) { SRC_DIRS.forEach(function(srcDir) {
convertAll(srcDir, CONV_DIR, opt_relPath || []); convertAll(srcDir, CONV_DIR, relPath);
}); });
}; if (writeSpawnFailures.length >= 1) {
print('********* failures **********');
writeSpawnFailures.forEach(function(failure) {
print(failure.error + ': ' + toRelPathStr(failure.relPath));
});
throw writeSpawnFailures[0].error;
}
}
t262.convert = convert; t262.convert = convert;
/** /**
@ -359,7 +408,7 @@
* runner. * runner.
*/ */
function buildSection(pathStr) { function buildSection(pathStr) {
var path = platform.toPath(pathStr); var path = toPath(pathStr);
if (!platform.isDirectory(path)) { throw new Error('not dir: ' + path); } if (!platform.isDirectory(path)) { throw new Error('not dir: ' + path); }
var jsFiles = platform.ls(path).filter(function(name) { var jsFiles = platform.ls(path).filter(function(name) {
@ -382,7 +431,7 @@
tests: testRecords tests: testRecords
} }
}; };
}; }
t262.buildSection = buildSection; t262.buildSection = buildSection;
/** /**
@ -403,14 +452,21 @@
if (hasJS) { if (hasJS) {
var name = relPath[relPath.length -1] + '.json'; var name = relPath[relPath.length -1] + '.json';
var outFilePath = outBase.concat([name]); var outFilePath = outBase.concat([name]);
platform.writeSpawn( try {
[ME_PATH], platform.writeSpawn(
't262.asJSONTxt(t262.buildSection("' + [ME_PATH],
platform.toPathStr(inPath) + '"))', 't262.asJSONTxt(t262.buildSection("' +
void 0, toPathStr(inPath) + '"))',
outFilePath); void 0,
outFilePath);
} catch (err) {
writeSpawnFailures.push({
error: err,
path: relPath
});
}
} }
}; }
t262.buildAll = buildAll; t262.buildAll = buildAll;
/** /**
@ -421,12 +477,13 @@
* files. Once we switch over to converted as the maintained * files. Once we switch over to converted as the maintained
* sources, we should change this. * sources, we should change this.
*/ */
function buildWebSite(opt_relPath) { function buildWebSite(opt_relPathStr) {
var relPath = opt_relPathStr ? toRelPath(opt_relPathStr) : [];
SRC_DIRS.forEach(function(srcDir) { SRC_DIRS.forEach(function(srcDir) {
buildAll(srcDir, OUT_DIR, opt_relPath || []); buildAll(srcDir, OUT_DIR, relPath);
}); });
// buildAll(CONV_DIR, OUT_DIR, opt_relPath || []); // buildAll(CONV_DIR, OUT_DIR, relPath);
}; }
t262.buildWebSite = buildWebSite; t262.buildWebSite = buildWebSite;
})(this); })(this);

View File

@ -34,11 +34,16 @@
/** /**
* Appends a bunch of RegExps together into a single RegExp, * Appends a bunch of RegExps together into a single RegExp,
* solving both the RegExp-one-liner problem and the doubled * solving both the RegExp-one-liner problem and the doubled
* backslash problem when composing literal string. * backslash problem when composing literal strings.
* *
* <p>The arguments can be any mixture of RegExps and strings. The * <p>The arguments can be any mixture of RegExps and strings. By
* strings are added as is without escaping -- BEWARE. If * expressing the portions that should be well formed regexps as
* arguments[0] is a RegExp, we use its flag on the resuting RegExp. * regexps, we catch well-formedness errors within such a portion
* separately. The strings are added as is without escaping --
* BEWARE. By not escaping the strings, we can use them to
* represent the individually unbalanced fragments, like capturing
* parens, around other regexps. If arguments[0] is a RegExp, we
* use its flags on the resuting RegExp.
* *
* <p>Not platform dependent, so does not really belong in this * <p>Not platform dependent, so does not really belong in this
* file. * file.
@ -95,23 +100,39 @@
return path; return path;
} }
/**
* Converts a relPath to a relPathStr.
*
* A relPath is an array of filenames relative to some base onto
* which it will be concatenated before use.
*/
function toRelPathStr(relPath) {
validatePath(relPath);
return relPath.join('/');
}
platform.toRelPathStr = toRelPathStr;
/** /**
* Converts a path to a pathStr. * Converts a path to a pathStr.
* *
* A path is an array of filenames relative to TEST262_ROOT. A * A path is an array of filenames relative to TEST262_ROOT. A
* pathStr is a (possibly fully qualified string) for referring to * pathStr is a (possibly fully qualified string) for referring to
* that string on the current platform, according to the operations * that file on the current platform, according to the operations
* in this *Platform.js file. * in this *Platform.js file.
*/ */
function toPathStr(path) { function toPathStr(path) {
validatePath(path); validatePath(path);
return TEST262_ROOT.concat(path).join('/'); return TEST262_ROOT.concat(path).join('/');
}; }
platform.toPathStr = toPathStr; platform.toPathStr = toPathStr;
/** /**
* Returns the text found at path, with newlines normalized and * Returns the text found at path, with newlines normalized and
* any initial BOM (Unicode Byte Order Mark) removed. * any initial BOM (Unicode Byte Order Mark) removed.
*
* Note: Don't simply revise this (without renamings) to follow the
* general pattern of also defining a local 'read' function, as it
* will mask the v8 shell's read function, which we use.
*/ */
platform.read = function(path) { platform.read = function(path) {
var text = read(toPathStr(path)). var text = read(toPathStr(path)).
@ -153,12 +174,12 @@
* @returns If there is a target, then the null string. Otherwise, * @returns If there is a target, then the null string. Otherwise,
* the string result of evaluating opt_exprSrc. * the string result of evaluating opt_exprSrc.
*/ */
platform.writeSpawn = function(scriptPaths, function writeSpawn(scriptPaths,
opt_exprSrc, opt_exprSrc,
opt_args, opt_args,
opt_targetPath, opt_targetPath,
opt_spawn_required, opt_spawn_required,
opt_forceNonStrict) { opt_forceNonStrict) {
if (opt_exprSrc && !opt_targetPath && !opt_spawn_required) { if (opt_exprSrc && !opt_targetPath && !opt_spawn_required) {
var str = '(function(/*var_args*/) {'; var str = '(function(/*var_args*/) {';
if (opt_forceNonStrict !== 'forceNonStrict') { if (opt_forceNonStrict !== 'forceNonStrict') {
@ -182,8 +203,21 @@
} }
if (VERBOSE || DRY_RUN) { print(cmd); } if (VERBOSE || DRY_RUN) { print(cmd); }
if (DRY_RUN) { return ''; } if (DRY_RUN) { return ''; }
return os.system('bash', ['-c', cmd]); try {
}; return os.system('bash', ['-c', cmd]);
} catch (err) {
if (opt_targetPath) {
// The error we catch is almost certainly less interesting
// than the one unfortunately written to the target file.
var message = 'failed: ' + cmd + '\n' +
platform.read(opt_targetPath);
os.system('rm', [toPathStr(opt_targetPath)]);
throw new Error(message);
}
throw err;
}
}
platform.writeSpawn = writeSpawn;
////////////////// Only needed for building ///////////////////// ////////////////// Only needed for building /////////////////////
@ -193,7 +227,7 @@
* On platforms (like SES) where this can be a safely confining * On platforms (like SES) where this can be a safely confining
* evaluation, it should be. The implementation here is not safe. * evaluation, it should be. The implementation here is not safe.
*/ */
platform.evalExprIn = function(exprSrc, env, opt_forceNonStrict) { function evalExprIn(exprSrc, env, opt_forceNonStrict) {
var varNames = Object.getOwnPropertyNames(env); var varNames = Object.getOwnPropertyNames(env);
var str = '(function(' + varNames.join(',') + ') {'; var str = '(function(' + varNames.join(',') + ') {';
if (opt_forceNonStrict !== 'forceNonStrict') { if (opt_forceNonStrict !== 'forceNonStrict') {
@ -203,12 +237,23 @@
return (1,eval)(str).apply(void 0, varNames.map(function(varName) { return (1,eval)(str).apply(void 0, varNames.map(function(varName) {
return env[varName]; return env[varName];
})); }));
}; }
platform.evalExprIn = evalExprIn;
/**
* Converts a relPathStr to a relPath.
*
* <p>See toRelPathStr.
*/
function toRelPath(relPathStr) {
return validatePath(relPathStr.split('/'));
}
platform.toRelPath = toRelPath;
/** /**
* Converts a pathStr to a path. * Converts a pathStr to a path.
* *
* See toPathStr. * <p>See toPathStr.
*/ */
function toPath(pathStr) { function toPath(pathStr) {
if (pathStr[0] === '/') { if (pathStr[0] === '/') {
@ -225,24 +270,38 @@
/** /**
* Does path name a directory? * Does path name a directory?
*/ */
platform.isDirectory = function(path) { function isDirectory(path) {
var fileOut = os.system('file', [toPathStr(path)]); // var fileOut = os.system('file', [toPathStr(path)]);
var fileMatch = fileOut.match(/:\s*([^:]*)\s*$/); // var fileMatch = fileOut.match(/:\s*([^:]*)\s*$/);
if (!fileMatch) { return null; } // if (!fileMatch) { return null; }
var fileType = fileMatch[1].trim(); // var fileType = fileMatch[1].trim();
return fileType === 'directory'; // return fileType === 'directory';
}; try {
os.system('test', ['-d', toPathStr(path)]);
return true;
} catch (x) {
return false;
}
}
platform.isDirectory = isDirectory;
/** /**
* A list of the filenames found in path, which must name a * A list of the filenames found in path, which must name a
* directory. * directory.
*/ */
platform.ls = function(path) { function ls(path) {
var pathStr = toPathStr(path); var pathStr = toPathStr(path);
var lines = os.system('ls', [pathStr]).trim(); if (!isDirectory(path)) { return []; }
var lines;
try {
lines = os.system('ls', [pathStr]).trim();
} catch (err) {
throw err;
}
if (lines === '') { return []; } if (lines === '') { return []; }
return lines.split('\n'); return lines.split('\n');
}; }
platform.ls = ls;
/** /**
* Emits the jsonRecord serialized as JSON, either compactly or * Emits the jsonRecord serialized as JSON, either compactly or
@ -257,7 +316,7 @@
} }
global.t262.asJSONTxt = platform.asJSONTxt = asJSONTxt; global.t262.asJSONTxt = platform.asJSONTxt = asJSONTxt;
platform.mkdir = function(path) { function mkdir(path) {
var pathStr = toPathStr(path); var pathStr = toPathStr(path);
if (DRY_RUN) { if (DRY_RUN) {
print('mkdir ' + pathStr); print('mkdir ' + pathStr);
@ -269,7 +328,8 @@
print('***could not mkdir: ' + pathStr); print('***could not mkdir: ' + pathStr);
throw err; throw err;
} }
}; }
platform.mkdir = mkdir;
////////////////// Only needed for running ////////////////////// ////////////////// Only needed for running //////////////////////