Switch carto to be synchronous.

This commit is contained in:
Young Hahn 2014-05-20 16:01:43 -04:00
parent cd18bea7ba
commit c5d8f4510e
6 changed files with 110 additions and 138 deletions

View File

@ -204,21 +204,20 @@ The `Renderer` interface is the main API for developers, and it takes an MML fil
// - input (the name or identifier of the file being parsed)
// - data (a string containing the MML or an object of MML)
var carto = require('carto');
new carto.Renderer({
try {
var output = new carto.Renderer({
filename: input,
local_data_dir: path.dirname(input),
}).render(data, function(err, output) {
if (err) {
if (Array.isArray(err)) {
err.forEach(function(e) {
carto.writeError(e, options);
});
} else { throw err; }
} else {
sys.puts(output);
}
});
}).render(data);
} catch(err) {
if (Array.isArray(err)) {
err.forEach(function(e) {
carto.writeError(e, options);
});
} else { throw err; }
}
console.log(output);
### Vim

View File

@ -65,26 +65,13 @@ function compileMML(err, data) {
console.error(err);
process.exit(1);
}
var renderer = new carto.Renderer({
filename: input,
benchmark: options.benchmark,
ppi: options.ppi
});
try {
var renderer = new carto.Renderer({
filename: input,
benchmark: options.benchmark,
ppi: options.ppi
});
renderer.render(data, function(err, output) {
if (err) {
console.error(err);
throw err;
process.exit(1);
} else {
if (!options.benchmark) {
console.log(output);
} else {
var duration = (+new Date) - start;
console.log('TOTAL: ' + (duration) + 'ms');
}
}
});
var output = renderer.render(data);
} catch (e) {
if (e.stack) {
console.error(e.stack);
@ -93,6 +80,12 @@ function compileMML(err, data) {
}
process.exit(1);
}
if (!options.benchmark) {
console.log(output);
} else {
var duration = (+new Date) - start;
console.log('TOTAL: ' + (duration) + 'ms');
}
};
function compileMSS(err, data) {
@ -100,26 +93,13 @@ function compileMSS(err, data) {
console.error(err);
process.exit(1);
}
var renderer = new carto.Renderer({
filename: path.basename(input),
benchmark: options.benchmark,
ppi: options.ppi
});
try {
var renderer = new carto.Renderer({
filename: path.basename(input),
benchmark: options.benchmark,
ppi: options.ppi
});
renderer.renderMSS(data, function(err, output) {
if (err) {
console.error(err);
throw err;
process.exit(1);
} else {
if (!options.benchmark) {
console.log(output);
} else {
var duration = (+new Date) - start;
console.log('TOTAL: ' + (duration) + 'ms');
}
}
});
var output = renderer.renderMSS(data);
} catch (e) {
if (e.stack) {
console.error(e.stack);
@ -128,6 +108,12 @@ function compileMSS(err, data) {
}
process.exit(1);
}
if (!options.benchmark) {
console.log(output);
} else {
var duration = (+new Date) - start;
console.log('TOTAL: ' + (duration) + 'ms');
}
};
try {

View File

@ -223,7 +223,7 @@ carto.Parser = function Parser(env) {
// Start with the primary rule.
// The whole syntax tree is held under a Ruleset node,
// with the `root` property set to true, so no `{}` are
// output. The callback is called when the input is parsed.
// output.
root = new tree.Ruleset([], $(this.parsers.primary));
root.root = true;

View File

@ -12,9 +12,8 @@ carto.Renderer = function Renderer(env, options) {
* XML Style fragment (mostly useful for debugging)
*
* @param {String} data the mss contents as a string.
* @param {Object} callback renderer environment options.
*/
carto.Renderer.prototype.renderMSS = function render(data, callback) {
carto.Renderer.prototype.renderMSS = function render(data) {
// effects is a container for side-effects, which currently
// are limited to FontSets.
var env = _(this.env).defaults({
@ -24,7 +23,7 @@ carto.Renderer.prototype.renderMSS = function render(data, callback) {
});
if (!carto.tree.Reference.setVersion(this.options.mapnik_version)) {
return callback(new Error("Could not set mapnik version to " + this.options.mapnik_version), null);
throw new Error("Could not set mapnik version to " + this.options.mapnik_version);
}
var output = [];
@ -58,8 +57,8 @@ carto.Renderer.prototype.renderMSS = function render(data, callback) {
if (env.benchmark) console.timeEnd(bench_name);
}
if (env.benchmark) console.timeEnd('Total Style generation');
if (env.errors) return callback(env.errors);
return callback(null, output.join('\n'));
if (env.errors) throw env.errors;
return output.join('\n');
};
/**
@ -67,9 +66,8 @@ carto.Renderer.prototype.renderMSS = function render(data, callback) {
* fully-localized XML file ready for Mapnik2 consumption
*
* @param {String} m - the JSON file as a string.
* @param {Object} callback - renderer environment options.
*/
carto.Renderer.prototype.render = function render(m, callback) {
carto.Renderer.prototype.render = function render(m) {
// effects is a container for side-effects, which currently
// are limited to FontSets.
var env = _(this.env).defaults({
@ -80,7 +78,7 @@ carto.Renderer.prototype.render = function render(m, callback) {
});
if (!carto.tree.Reference.setVersion(this.options.mapnik_version)) {
return callback(new Error("Could not set mapnik version to " + this.options.mapnik_version), null);
throw new Error("Could not set mapnik version to " + this.options.mapnik_version);
}
var output = [];
@ -89,13 +87,12 @@ carto.Renderer.prototype.render = function render(m, callback) {
var definitions = _(m.Stylesheet).chain()
.map(function(s) {
if (typeof s == 'string') {
callback(new Error("Stylesheet object is expected not a string: '" + s + "'"));
throw new Error("Stylesheet object is expected not a string: '" + s + "'");
}
// Passing the environment from stylesheet to stylesheet,
// allows frames and effects to be maintained.
env = _(env).extend({filename:s.id});
// @TODO try/catch?
var time = +new Date(),
root = (carto.Parser(env)).parse(s.data);
if (env.benchmark)
@ -149,16 +146,10 @@ carto.Renderer.prototype.render = function render(m, callback) {
return e.toXML(env);
}).join('\n'));
var map_properties;
try {
map_properties = getMapProperties(m, definitions, env);
} catch (err) {
env.error(err);
return callback(err);
}
var map_properties = getMapProperties(m, definitions, env);
// Exit on errors.
if (env.errors) return callback(env.errors);
if (env.errors) throw env.errors;
// Pass TileJSON and other custom parameters through to Mapnik XML.
var parameters = _(m).reduce(function(memo, v, k) {
@ -222,7 +213,7 @@ carto.Renderer.prototype.render = function render(m, callback) {
'<!DOCTYPE Map[]>\n' +
'<Map' + properties +'>\n');
output.push('</Map>');
return callback(null, output.join('\n'));
return output.join('\n');
};
/**

View File

@ -11,34 +11,30 @@ var helper = require('./support/helper');
describe('Rendering mss', function() {
helper.files('rendering-mss', 'mss', function(file) {
it('should render mss ' + path.basename(file) + ' correctly', function(done) {
it('should render mss ' + path.basename(file) + ' correctly', function() {
var completed = false;
var renderResult;
var mss = helper.mss(file);
new carto.Renderer({
paths: [ path.dirname(file) ],
data_dir: path.join(__dirname, '../data'),
local_data_dir: path.join(__dirname, 'rendering'),
filename: file
}).renderMSS(mss, function (err, output) {
if (err) {
if (Array.isArray(err)){
err.forEach(carto.writeError);
done();
} else {
throw err;
done();
}
try {
var output = new carto.Renderer({
paths: [ path.dirname(file) ],
data_dir: path.join(__dirname, '../data'),
local_data_dir: path.join(__dirname, 'rendering'),
filename: file
}).renderMSS(mss);
} catch(err) {
if (Array.isArray(err)){
err.forEach(carto.writeError);
} else {
var expected = file.replace(path.extname(file),'')+'.xml';
if (!existsSync(expected)) {
fs.writeFileSync(expected,output);
}
var expected_data = fs.readFileSync(expected).toString();
assert.equal(output,expected_data);
done();
throw err;
}
});
}
var expected = file.replace(path.extname(file),'')+'.xml';
if (!existsSync(expected)) {
fs.writeFileSync(expected,output);
}
var expected_data = fs.readFileSync(expected).toString();
assert.equal(output,expected_data);
});
});
});

View File

@ -12,52 +12,52 @@ helper.files('rendering', 'mml', function(file) {
var completed = false;
var renderResult;
var mml = helper.mml(file);
new carto.Renderer({
paths: [ path.dirname(file) ],
data_dir: path.join(__dirname, '../data'),
local_data_dir: path.join(__dirname, 'rendering'),
filename: file
}).render(mml, function (err, output) {
if (err) {
if (Array.isArray(err)){
err.forEach(carto.writeError);
} else {
throw err;
}
try {
var output = new carto.Renderer({
paths: [ path.dirname(file) ],
data_dir: path.join(__dirname, '../data'),
local_data_dir: path.join(__dirname, 'rendering'),
filename: file
}).render(mml);
} catch(err) {
if (Array.isArray(err)){
err.forEach(carto.writeError);
return done();
} else {
var result = helper.resultFile(file);
renderResult = output;
helper.compareToXMLFile(result, output, function(err,expected_json,actual_json) {
completed = true;
var actual = file.replace(path.extname(file),'') + '-actual.json';
var expected = file.replace(path.extname(file),'') + '-expected.json';
if (err) {
// disabled since it can break on large diffs
/*
console.warn(
helper.stylize("Failure", 'red') + ': ' +
helper.stylize(file, 'underline') +
' differs from expected result.');
helper.showDifferences(err);
throw '';
*/
fs.writeFileSync(actual,JSON.stringify(actual_json,null,4));
fs.writeFileSync(expected,JSON.stringify(expected_json,null,4));
throw new Error('failed: xml ' + result + ' in json form does not match expected result:\n' + actual + ' (actual)\n' + expected + ' (expected)');
} else {
// cleanup any actual renders that no longer fail
try {
fs.unlinkSync(actual);
fs.unlinkSync(expected);
} catch (err) {}
}
done();
}, [
helper.removeAbsoluteImages,
helper.removeAbsoluteDatasources
]);
return done(err);
}
});
}
var result = helper.resultFile(file);
renderResult = output;
helper.compareToXMLFile(result, output, function(err,expected_json,actual_json) {
completed = true;
var actual = file.replace(path.extname(file),'') + '-actual.json';
var expected = file.replace(path.extname(file),'') + '-expected.json';
if (err) {
// disabled since it can break on large diffs
/*
console.warn(
helper.stylize("Failure", 'red') + ': ' +
helper.stylize(file, 'underline') +
' differs from expected result.');
helper.showDifferences(err);
throw '';
*/
fs.writeFileSync(actual,JSON.stringify(actual_json,null,4));
fs.writeFileSync(expected,JSON.stringify(expected_json,null,4));
throw new Error('failed: xml ' + result + ' in json form does not match expected result:\n' + actual + ' (actual)\n' + expected + ' (expected)');
} else {
// cleanup any actual renders that no longer fail
try {
fs.unlinkSync(actual);
fs.unlinkSync(expected);
} catch (err) {}
}
done();
}, [
helper.removeAbsoluteImages,
helper.removeAbsoluteDatasources
]);
// beforeExit(function() {
// if (!completed && renderResult) {