Complete switch over to pegjs

This commit is contained in:
Jeremy Ruston 2011-12-28 22:07:17 +00:00
parent b27a99a7fb
commit ed2e2ab14c
10 changed files with 34 additions and 23 deletions

View File

@ -16,8 +16,10 @@ Options and their defaults are:
noNames: false, noNames: false,
cascadeDefaults: false, cascadeDefaults: false,
allowEval: true allowEval: true
sandbox: null
globals: null globals: null
`sandbox` is the sandbox object used to evaluate JavaScript parameters
`globals` is the global variable object provided to evaluated parameters `globals` is the global variable object provided to evaluated parameters
\*/ \*/
@ -26,9 +28,8 @@ Options and their defaults are:
/*jslint node: true */ /*jslint node: true */
"use strict"; "use strict";
var sandbox = require("./Sandbox.js").sandbox;
var ArgParser = function(argString,options) { var ArgParser = function(argString,options) {
options = options || {};
var parseToken = function(match,p) { var parseToken = function(match,p) {
var n; var n;
if(match[p]) { // Double quoted if(match[p]) { // Double quoted
@ -38,7 +39,7 @@ var ArgParser = function(argString,options) {
} else if(match[p+2]) { // Double-square-bracket quoted } else if(match[p+2]) { // Double-square-bracket quoted
n = match[p+2]; n = match[p+2];
} else if(match[p+3]) { // Double-brace quoted } else if(match[p+3]) { // Double-brace quoted
n = options.allowEval === false ? match[p+3] : sandbox(match[p+3],options.globals); n = options.allowEval === false ? match[p+3] : options.sandbox.execute(match[p+3],options.globals);
} else if(match[p+4]) { // Unquoted } else if(match[p+4]) { // Unquoted
n = match[p+4]; n = match[p+4];
} else if(match[p+5]) { // empty quote } else if(match[p+5]) { // empty quote

View File

@ -14,6 +14,7 @@ var WikiStore = require("./WikiStore.js").WikiStore,
tiddlerInput = require("./TiddlerInput.js"), tiddlerInput = require("./TiddlerInput.js"),
tiddlerOutput = require("./TiddlerOutput.js"), tiddlerOutput = require("./TiddlerOutput.js"),
WikiTextProcessor = require("./WikiTextProcessor.js").WikiTextProcessor, WikiTextProcessor = require("./WikiTextProcessor.js").WikiTextProcessor,
Sandbox = require("./Sandbox.js").Sandbox,
Navigators = require("./Navigators.js").Navigators, Navigators = require("./Navigators.js").Navigators,
StoryNavigator = require("./StoryNavigator.js").StoryNavigator; StoryNavigator = require("./StoryNavigator.js").StoryNavigator;
@ -58,6 +59,9 @@ for(t=0; t<tiddlers.length; t++) {
store.addTiddler(new Tiddler(tiddlers[t])); store.addTiddler(new Tiddler(tiddlers[t]));
} }
// Set up the sandbox for evaluated macro parameters
store.sandbox = new Sandbox(store.getTiddlerText("javascript.pegjs"));
// Install the standard navigators // Install the standard navigators
var navigators = new Navigators({ var navigators = new Navigators({
document: document, document: document,

View File

@ -57,7 +57,7 @@ var Recipe = function(options,callback) {
this.recipeQueue = async.queue(function(task,callback) { this.recipeQueue = async.queue(function(task,callback) {
retrieveFile(task.filepath,task.contextPath,function(err,data) { retrieveFile(task.filepath,task.contextPath,function(err,data) {
if(err) { if(err) {
callback(err); me.callback(err);
} else { } else {
me.processRecipeFile(task.recipe,data.text,data.path); me.processRecipeFile(task.recipe,data.text,data.path);
callback(null); callback(null);
@ -342,7 +342,7 @@ Recipe.prototype.cookRss = function()
getRssTiddlers = function(sortField,excludeTag) { getRssTiddlers = function(sortField,excludeTag) {
var r = []; var r = [];
me.store.forEachTiddler(sortField,excludeTag,function(title,tiddler) { me.store.forEachTiddler(sortField,excludeTag,function(title,tiddler) {
if(!tiddler.hasTag(excludeTag)) { if(!tiddler.hasTag(excludeTag) && tiddler.fields.modified !== undefined) {
r.push(tiddler); r.push(tiddler);
} }
}); });

View File

@ -9,9 +9,13 @@ Execute a fragment of JavaScript in a sandbox
/*jslint evil: true, node: true */ /*jslint evil: true, node: true */
"use strict"; "use strict";
var uglify = require("uglify-js"); var pegjs = require("pegjs");
var sandbox = function(code,globals) { var Sandbox = function(parserText) {
this.parser = pegjs.buildParser(parserText);
};
Sandbox.prototype.execute = function(code,globals) {
var globalNames = [], var globalNames = [],
globalValues = [], globalValues = [],
collectGlobals = function(globals) { collectGlobals = function(globals) {
@ -36,20 +40,20 @@ var sandbox = function(code,globals) {
out.push(code); out.push(code);
out.push(";})"); out.push(";})");
// Parse the code // Parse the code
var tree = uglify.parser.parse(out.join("")); var code = out.join(""),
tree = this.parser.parse(out.join(""));
// XXX: Sanitise the code by checking for references to globals, stripping out eval() // XXX: Sanitise the code by checking for references to globals, stripping out eval()
// Recompile the code console.log(tree);
var compiledCode = uglify.uglify.gen_code(tree);
// Execute it // Execute it
var result; var result;
try { try {
result = eval(compiledCode).apply(null,globalValues); result = eval(code).apply(null,globalValues);
} catch(err) { } catch(err) {
result = "{{** Evaluation error: " + err + " **}}"; result = "{{** Evaluation error: " + err + " **}}";
} }
return result; return result;
}; };
exports.sandbox = sandbox; exports.Sandbox = Sandbox;
})(); })();

View File

@ -21,6 +21,7 @@ var WikiStore = function WikiStore(options) {
this.textProcessors = {}; this.textProcessors = {};
this.tiddlerSerializers = {}; this.tiddlerSerializers = {};
this.tiddlerDeserializers = {}; this.tiddlerDeserializers = {};
this.sandbox = options.sandbox;
this.shadows = options.shadowStore !== undefined ? options.shadowStore : new WikiStore({ this.shadows = options.shadowStore !== undefined ? options.shadowStore : new WikiStore({
shadowStore: null shadowStore: null
}); });

View File

@ -134,7 +134,8 @@ WikiTextRenderer.prototype.executeMacro = function(macroNode,title) {
var argOptions = { var argOptions = {
globals: { globals: {
title: title title: title
} },
sandbox: this.store.sandbox
}; };
for(var g in macroInfo.argOptions) { for(var g in macroInfo.argOptions) {
argOptions[g] = macroInfo.argOptions[g]; argOptions[g] = macroInfo.argOptions[g];

3
parsers/split.recipe Normal file
View File

@ -0,0 +1,3 @@
tiddler: javascript.pegjs
title: javascript.pegjs
type: text/x-tiddlywiki-parser

View File

@ -107,8 +107,8 @@ var commandLineSwitches = {
recipe = new Recipe({ recipe = new Recipe({
filepath: args[0], filepath: args[0],
store: store store: store
},function() { },function(err) {
callback(null); callback(err);
}); });
} }
} }

View File

@ -10,3 +10,5 @@ TiddlyWiki5 gains new capabilities through a [[completely rebuilt architecture|T
TiddlyWiki5 also functions as the build system for earlier versions of TiddlyWiki, replacing the elderly Cook and Ginsu tools (see https://github.com/TiddlyWiki/cooker for details). See the CommandLineInterface for details. TiddlyWiki5 also functions as the build system for earlier versions of TiddlyWiki, replacing the elderly Cook and Ginsu tools (see https://github.com/TiddlyWiki/cooker for details). See the CommandLineInterface for details.
<<list all>> <<list all>>
<<echo {{2+2}}>>

View File

@ -3,6 +3,7 @@ copyright: ../copyright.txt
style: styles.css style: styles.css
recipe: tiddlers/split.recipe recipe: tiddlers/split.recipe
recipe: ../parsers/split.recipe
jslib: ../test/tiddlywiki.2.6.5/source/tiddlywiki/jquery/jquery.js jslib: ../test/tiddlywiki.2.6.5/source/tiddlywiki/jquery/jquery.js
@ -22,14 +23,8 @@ jsmodule: ../js/Navigators.js
jsmodule: ../js/StoryNavigator.js jsmodule: ../js/StoryNavigator.js
jsmodule: ../js/Main.js jsmodule: ../js/Main.js
jsmodule: ../node_modules/uglify-js/lib/parse-js.js jsmodule: ../node_modules/pegjs/lib/peg.js
title: lib/parse-js title: pegjs
jsmodule: ../node_modules/uglify-js/lib/process.js
title: lib/process
jsmodule: ../node_modules/uglify-js/lib/squeeze-more.js
title: lib/squeeze-more
jsmodule: ../node_modules/uglify-js/uglify-js.js
title: uglify-js
jsbootstart: BootStart.js jsbootstart: BootStart.js
jsbootend: BootLoader.js jsbootend: BootLoader.js