diff --git a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js index f6ba739..e23f87a 100644 --- a/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js +++ b/sel-blocks-fx_xpi/chrome/content/extensions/selblocks.js @@ -157,16 +157,137 @@ function $X(xpath, contextNode, resultType) { return null; }; - //=============== Call/Scope Stack handling =============== var symbols = {}; // command indexes stored by name: function names var blockDefs = null; // static command definitions stored by command index var callStack = null; // command execution stack + var contextManager; // makes block scoped variables work + // intentionally global var + storedVarsGlobal = storedVars; + /** + * Manages variable scope for functions, blocks, etc. + * @class ContextManager + */ + function ContextManager() { + // intentionally global var + storedVarsLocal = Object.create(storedVarsGlobal); + storedVars = storedVarsLocal; + this.contexts = []; + this.enter(); + } + /** + * Enters a new variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.enter = function enterContext() { + var _o = storedVars; + var context = { + here : Object.create(storedVars), + back : _o + }; + this.contexts.push(context); + storedVars = context.here; + storedVarsLocal = context.here; + }; + /** + * Exits to the previous variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.exit = function exitContext() { + if (this.contexts.length > 0) { + var context = this.contexts.pop(); + storedVars = context.back; + storedVarsLocal = context.back; + } else { + throw new Error("No context to exit from"); + } + }; + /** + * Resets to the top variable context. + * @methodOf ContextManager. + */ + ContextManager.prototype.reset = function exitContext() { + if (this.contexts.length > 0) { + storedVars = storedVarsGlobal; + storedVarsLocal = storedVarsGlobal; + this.contexts = []; + this.enter(); + } else { + throw new Error("No context to exit from"); + } + }; + /** + * Stores variable into the context chain in the last parent where it was + * defined. This allows values to bubble up to their relevant parent so that + * you don't have to pass everything in global scope. The variable must exist + * in a parent scope in order to be caught there, otherwise it will get to + * the global scope and be set there. + * @param {String} propName The name of the variable. + * @param {Mixed} val Any value you could set for a variable. + */ + ContextManager.prototype.storeAtClosestContextWithPropName = + function storeAtClosestContextWithPropName (propName, val) { + var out = undefined; + var idx = this.contexts.length - 1; + while (idx >= 0 && out === undefined) { + if(this.contexts[idx].here.hasOwnProperty(propName)) { + this.contexts[idx].here[String(propName)] = val; + out = true; + } + idx--; + } + if(out === undefined) { + storedVarsGlobal[String(propName)] = val; + $$.LOG.warn(String(propName) + " not found, setting global variable"); + } + }; + contextManager = new ContextManager(); + /** + * State information about the cache. + * currentCaseTitle is the current case displayed in the UI + * activeCaseTitle is the cashed case where commands are actually being pulled + * from. + * commandIndex is the current index of the commands array in the active case + * suites are the cached test suites commands, symbols, and blockDefs + */ + var cachedCommandsData = { + initializing : true, + currentCaseTitle : '', + activeCaseTitle : '', + commandIndex : 0, + suites : Object.create(null), + /** + * Caches information about the current test case + */ + cacheCommands : function cacheCacheCommands(symbols, commands, blockDefs) { + cachedCommandsData.initializing = false; + cachedCommandsData.suites[cachedCommandsData.currentCaseTitle] = { + 'symbols' : symbols, + 'commands' : commands, + 'blockDefs' : blockDefs + } + }, + /** + * Starts a new suite cache. + */ + init : function cacheInit() { + cachedCommandsData.initializing = true; + var _mytitle = testCase.title || "untitiled"; + // the current case displayed in the IDE + cachedCommandsData.currentCaseTitle = String(_mytitle); + // the current case for looking up functions + cachedCommandsData.activeCaseTitle = String(_mytitle); + // the index used for executing commands, this is decoupled from the + // testCase.debugIndex because what's being executed doesn't always + // move the row cursor in the UI anymore. + cachedCommandsData.commandIndex = 0; + } + }; // the idx of the currently executing command function idxHere() { - return testCase.debugContext.debugIndex; + return cachedCommandsData.commandIndex; } // Command structure definitions, stored by command index @@ -184,7 +305,13 @@ function $X(xpath, contextNode, resultType) { // retrieve the blockDef at the given command idx function blkDefAt(idx) { - return blockDefs[idx]; + var where; + if(cachedCommandsData.initializing === true) { + where = blockDefs[idx]; + } else { + where = cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].blockDefs[idx]; + } + return where; } // retrieve the blockDef for the currently executing command function blkDefHere() { @@ -242,33 +369,43 @@ function $X(xpath, contextNode, resultType) { if (!this.started) { this.started = true; this.debugIndex = testCase.startPoint ? testCase.commands.indexOf(testCase.startPoint) : 0; + cachedCommandsData.commandIndex = 0 + this.debugIndex; + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); } else { if (branchIdx !== null) { $$.LOG.info("branch => " + fmtCmdRef(branchIdx)); - this.debugIndex = branchIdx; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + this.debugIndex = branchIdx; + } + cachedCommandsData.commandIndex = branchIdx; branchIdx = null; } else { - this.debugIndex++; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + this.debugIndex++; + } + cachedCommandsData.commandIndex++; } } // skip over comments - while (this.debugIndex < testCase.commands.length) { - var command = testCase.commands[this.debugIndex]; + while (cachedCommandsData.commandIndex < cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands.length) { + var command = cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands[cachedCommandsData.commandIndex]; if (command.type === "command") { return command; } - this.debugIndex++; + if(cachedCommandsData.activeCaseTitle === cachedCommandsData.currentCaseTitle) { + this.debugIndex++; + } + cachedCommandsData.commandIndex++; } return null; } function setNextCommand(cmdIdx) { - assert(cmdIdx >= 0 && cmdIdx < testCase.commands.length, - " Cannot branch to non-existent command @" + (cmdIdx+1)); + assert(cmdIdx >= 0 && cmdIdx < cachedCommandsData.suites[String(cachedCommandsData.activeCaseTitle)].commands.length, + " Cannot branch to non-existent command " + String(cachedCommandsData.activeCaseTitle) + " @" + (cmdIdx+1)); branchIdx = cmdIdx; } - // Selenium calls reset(): // * before each single (double-click) command execution // * before a testcase is run @@ -278,6 +415,7 @@ function $X(xpath, contextNode, resultType) { { $$.LOG.trace("In tail intercept :: Selenium.reset()"); try { + contextManager.reset(); compileSelBlocks(); } catch (err) { @@ -303,6 +441,8 @@ function $X(xpath, contextNode, resultType) { // Assemble block relationships and symbol locations function compileSelBlocks() { + cachedCommandsData.init(); + symbols = {}; blockDefs = new BlockDefs(); var lexStack = new Stack(); var i; @@ -487,6 +627,7 @@ function $X(xpath, contextNode, resultType) { } throw new SyntaxError(cmdErrors.join("; ")); } + cachedCommandsData.cacheCommands(symbols, testCase.commands, blockDefs); //- command validation function assertNotAndWaitSuffix(cmdIdx) { assertCmd(cmdIdx, (testCase.commands[cmdIdx].command.indexOf("AndWait") === -1), @@ -589,7 +730,7 @@ function $X(xpath, contextNode, resultType) { notifyFatal("Invalid character(s) in " + desc + " name: '" + name + "'"); } } - + Selenium.prototype.doLabel = function() { // noop }; @@ -874,10 +1015,14 @@ function $X(xpath, contextNode, resultType) { $$.LOG.warn("bubbleToTryBlock() called outside of any try nesting"); } var tryState = unwindToBlock(_hasCriteria); + var ret; while (!tryState && $$.tcf.nestingLevel > -1 && callStack.length > 1) { var callFrame = callStack.pop(); $$.LOG.info("function '" + callFrame.name + "' aborting due to error"); - restoreVarState(callFrame.savedVars); + if (storedVars._result) { ret = storedVars._result; } + contextManager.exit(); + storedVars._result = ret; + //restoreVarState(callFrame.savedVars); tryState = unwindToBlock(_hasCriteria); } return tryState; @@ -1189,6 +1334,7 @@ function $X(xpath, contextNode, resultType) { activeBlockStack().push(loopState); var localVars = _validateFunc(loopState); loopState.savedVars = getVarState(localVars); + contextManager.enter(); initVarState(localVars); // because with-scope can reference storedVars only once they exist _initFunc(loopState); } @@ -1210,8 +1356,13 @@ function $X(xpath, contextNode, resultType) { assertRunning(); assertActiveScope(blkDefHere().beginIdx); var loopState = activeBlockStack().top(); + var ret; if (loopState.isComplete) { - restoreVarState(loopState.savedVars); + if (storedVars._result) { ret = storedVars._result; } + contextManager.exit(); + storedVars._result = ret; + + //restoreVarState(loopState.savedVars); activeBlockStack().pop(); // done, fall out of loop } @@ -1261,38 +1412,57 @@ function $X(xpath, contextNode, resultType) { // ================================================================================ Selenium.prototype.doCall = function(funcName, argSpec) { + var funcIdx, fName, caseName; assertRunning(); // TBD: can we do single execution, ie, run from this point then break on return? if (argSpec) { assertCompilable("var ", argSpec, ";", "Invalid call parameter(s)"); } - var funcIdx = symbols[funcName]; - assert(funcIdx!==undefined, " Function does not exist: " + funcName + "."); + if(funcName.match(/[.]/)) { + caseName = String(funcName.split(".")[0]); + fName = String(funcName.split(".")[1]); + } else { + caseName = String(cachedCommandsData.activeCaseTitle); + fName = String(funcName); + } + funcIdx = cachedCommandsData.suites[caseName].symbols[fName]; + assert(funcIdx!==undefined, " Function does not exist: " + funcName); + cachedCommandsData.activeCaseTitle = String(caseName); var activeCallFrame = callStack.top(); if (activeCallFrame.isReturning && activeCallFrame.returnIdx === idxHere()) { // returning from completed function - restoreVarState(callStack.pop().savedVars); + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); + callStack.pop() + //restoreVarState(callStack.pop().savedVars); } else { - // save existing variable state and set args as local variables + // pass supplied args to the function call through the call stack var args = parseArgs(argSpec); - var savedVars = getVarStateFor(args); - setVars(args); + // saved vars will be populated by the function call - callStack.push({ funcIdx: funcIdx, name: funcName, args: args, returnIdx: idxHere(), - savedVars: savedVars, blockStack: new Stack() }); + callStack.push({ funcIdx: funcIdx, name: fName, args: args, returnIdx: idxHere(), + savedVars: {}, blockStack: new Stack() }); // jump to function body setNextCommand(funcIdx); } }; - Selenium.prototype.doFunction = function(funcName) + Selenium.prototype.doFunction = function(funcName, paramString) { assertRunning(); - + var params, savedVars; var funcDef = blkDefHere(); var activeCallFrame = callStack.top(); if (activeCallFrame.funcIdx === idxHere()) { - // get parameter values + contextManager.enter(); + params = parseArgs(paramString, "suppress variable expansion"); + // caching the values of all storedVars specified in function signature. + //savedVars = getVarStateFor(params); + //activeCallFrame.savedVars = savedVars; + + // set default values supplied in function definition + setVars(params); + // overwrite local variables and defaults with the supplied values from + // the call setVars(activeCallFrame.args); } else { @@ -1300,11 +1470,11 @@ function $X(xpath, contextNode, resultType) { setNextCommand(funcDef.endIdx); } }; - Selenium.prototype.doScript = function(scrName) + Selenium.prototype.doScript = function(scrName, paramString) { $$.LOG.warn("The script command has been deprecated and will be removed in future releases." + " Please use function instead."); - Selenium.prototype.doFunction(scrName); + Selenium.prototype.doFunction(scrName, paramString); }; Selenium.prototype.doReturn = function(value) { returnFromFunction(null, value); @@ -1322,15 +1492,19 @@ function $X(xpath, contextNode, resultType) { if (transitionBubbling(Stack.isFunctionBlock)) { return; } + var ret; var endDef = blkDefHere(); var activeCallFrame = callStack.top(); if (activeCallFrame.funcIdx !== endDef.funcIdx) { // no active call, we're just skipping around a function block } else { - if (returnVal) { storedVars._result = evalWithVars(returnVal); } + if (returnVal) { ret = evalWithVars(returnVal); } + contextManager.exit(); + storedVars._result = ret; activeCallFrame.isReturning = true; // jump back to call command + cachedCommandsData.activeCaseTitle = String(cachedCommandsData.currentCaseTitle); setNextCommand(activeCallFrame.returnIdx); } } @@ -1347,7 +1521,63 @@ function $X(xpath, contextNode, resultType) { // ========= storedVars management ========= + + Selenium.prototype.doStoreGlobal = function(value, varName) { + storedVarsGlobal[varName] = value; + }; + + Selenium.prototype.doStoreEvalGlobal = function(value, varName) { + var val = evalWithVars(String(value)); + storedVarsGlobal[varName] = val; + }; + Selenium.prototype.doStoreGlobalText = function(target, varName) { + var element = this.page().findElement(target); + storedVarsGlobal[varName] = getText(element); + }; + + Selenium.prototype.doStoreGlobalAttribute = function(target, varName) { + storedVarsGlobal[varName] = this.page().findAttribute(target); + }; + + Selenium.prototype.doStoreLocal = function(value, varName) { + storedVarsLocal[varName] = value; + }; + + Selenium.prototype.doStoreEvalLocal = function(value, varName) { + var val = evalWithVars(String(value)); + storedVarsLocal[varName] = val; + }; + + Selenium.prototype.doStoreLocalText = function(target, varName) { + var element = this.page().findElement(target); + storedVarsLocal[varName] = getText(element); + }; + + Selenium.prototype.doStoreLocalAttribute = function(target, varName) { + storedVarsLocal[varName] = this.page().findAttribute(target); + }; + + Selenium.prototype.doStoreAt = function(value, varName) { + contextManager.storeAtClosestContextWithPropName(varName, value); + }; + + Selenium.prototype.doStoreEvalAt = function(value, varName) { + var val = evalWithVars(String(value)); + contextManager.storeAtClosestContextWithPropName(varName, val); + }; + + Selenium.prototype.doStoreAtText = function(target, varName) { + var element = this.page().findElement(target); + var value = getText(element); + contextManager.storeAtClosestContextWithPropName(varName, value); + }; + + Selenium.prototype.doStoreAtAttribute = function(target, varName) { + var value = this.page().findAttribute(target); + contextManager.storeAtClosestContextWithPropName(varName, value); + }; + function evalWithVars(expr) { var result = null; try { @@ -1360,15 +1590,37 @@ function $X(xpath, contextNode, resultType) { } return result; } - - function parseArgs(argSpec) { // comma-sep -> new prop-set + /** + * Parses a string of comma separated args that may contain assignments with + * equal signs. + * @param {String} argSpec The string representing arguments. + * @param {Null|Any} suppressEval If this is set to any truthy value then the + * values side of any arguments will not be evaluated with respect to the + * stored variables. + * @returns {Object} Returns an object whose properties are argument names and + * whose property values are the arguments values. If no value was supplied + * then the property will exist but it will be set to undefined. + * @example + * // storedVariables.bat = "XXXXXXX"; + * parseArgs('foo="bar",baz=bat'); + * // returns {foo:"bar", baz:"XXXXXXX"} + * parseArgs('foo="bar",baz=bat', "suppress eval"); + * // returns {foo:"bar", baz:"bat"} + */ + function parseArgs(argSpec, suppressEval) { // comma-sep -> new prop-set var args = {}; var parms = iexpr.splitList(argSpec, ","); var i; for (i = 0; i < parms.length; i++) { var keyValue = iexpr.splitList(parms[i], "="); validateName(keyValue[0], "parameter"); - args[keyValue[0]] = evalWithVars(keyValue[1]); + // boolean values suck, let me put any arbitrary string as the arg + // like "suppress variable expansion" so I can be clear about my intent. + if(suppressEval) { + args[keyValue[0]] = keyValue[1]; + } else { + args[keyValue[0]] = evalWithVars(keyValue[1]); + } } return args; } @@ -1377,11 +1629,20 @@ function $X(xpath, contextNode, resultType) { var i; for (i = 0; i < names.length; i++) { if (!storedVars[names[i]]) { - storedVars[names[i]] = null; + storedVars[names[i]] = undefined; } } } } + /** + * Sets the values of existing `args` properties to match `storedVars` + * @param {Object} args A simple value store where properties represent the + * the names of arguments and their values are the default values of those + * properties. If those same properties exist on `storedVars` they will be + * overwritten in the output object. + * @returns {Object} returns a simple object that can be used as `this` in + * `fn.call` and `fn.apply` etc. + */ function getVarStateFor(args) { // storedVars(prop-set) -> new prop-set var savedVars = {}; var varname; @@ -1390,6 +1651,13 @@ function $X(xpath, contextNode, resultType) { } return savedVars; } + /** + * Gets links to the storedVars specified. + * @param {Array} names An array of strings representing the storedVars + * properties that you want to copy/link to. + * @returns {Object} returns a simple object that can be used as `this` in + * `fn.call` and `fn.apply` etc. + */ function getVarState(names) { // storedVars(names) -> new prop-set var savedVars = {}; if (names) { @@ -1400,6 +1668,14 @@ function $X(xpath, contextNode, resultType) { } return savedVars; } + /** + * Overwrites values in storedVars with values supplied. + * @param {Object} args A simple value store where properties represent the + * the names of arguments and their values are the default values of those + * properties. If those same properties exist on `storedVars` they will be + * overwritten. + * @returns {Null} returns nothing. + */ function setVars(args) { // prop-set -> storedVars var varname; for (varname in args) { diff --git a/sel-blocksTests/CallGlobalFunction.html b/sel-blocksTests/CallGlobalFunction.html new file mode 100644 index 0000000..5066a9a --- /dev/null +++ b/sel-blocksTests/CallGlobalFunction.html @@ -0,0 +1,55 @@ + + + + + +CallGlobalFunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CallGlobalFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
getEvalglobalStoredVars.aGlobalVar = "reset";
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callGlobalFunctions.setGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
callGlobalFunctions 2.doStuff
+ + diff --git a/sel-blocksTests/CreateGlobalVars.html b/sel-blocksTests/CreateGlobalVars.html new file mode 100644 index 0000000..af27f19 --- /dev/null +++ b/sel-blocksTests/CreateGlobalVars.html @@ -0,0 +1,30 @@ + + + + + +CreateGlobalVars + + + + + + + + + + + + + + + + + + + + + +
CreateGlobalVars
getEvalglobalStoredVars = {};
getEvalglobalStoredVars = {};
getEvalglobalStoredVars = {};
+ + diff --git a/sel-blocksTests/DefineFunctionParameters - Base.html b/sel-blocksTests/DefineFunctionParameters - Base.html new file mode 100644 index 0000000..a7b8cf5 --- /dev/null +++ b/sel-blocksTests/DefineFunctionParameters - Base.html @@ -0,0 +1,81 @@ + + + + + + +DefineFunctionParameters - Base + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DefineFunctionParameters - Base
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionbobx,y
assertEval"${x}" === "overwritten"true
assertEvalstoredVars.y === undefinedtrue
endFunction
callbobx="overwritten"
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEvalstoredVars.y === undefinedfalse
assertEval"${y}" === "original";true
+ + diff --git a/sel-blocksTests/DefineFunctionParameters - With Default Values.html b/sel-blocksTests/DefineFunctionParameters - With Default Values.html new file mode 100644 index 0000000..cbf9f1d --- /dev/null +++ b/sel-blocksTests/DefineFunctionParameters - With Default Values.html @@ -0,0 +1,249 @@ + + + + + + +DefineFunctionParameters - With Default Values + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DefineFunctionParameters - With Default Values
storeoriginalx
storeoriginaly
assertEval"${x}" === "original";true
assertEval"${y}" === "original";true
functionleakTestx="fn default x",y="fn default y"
storeoverwrittenx
storeoverwritteny
endFunction
functiondefaultsTestx="fn default x",y="fn default y"
assertEval${x} === "fn default x"true
store"overwritten"x
assertEval${x} === "overwritten"true
assertEval${y} === "fn default y"true
store"overwritten"y
assertEval${y} === "overwritten"true
endFunction
calldefaultsTest
callleakTest
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTesty = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTestx = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
callleakTestx = "overwritten", y = "overwritten"
assertEval"${x}" === "fn default x"false
assertEval"${x}" === "overwritten"false
assertEval"${x}" === "original";true
assertEval"${y}" === "fn default y"false
assertEval"${y}" === "overwritten"false
assertEval"${y}" === "original";true
+ + diff --git a/sel-blocksTests/Function - Can Return Value.html b/sel-blocksTests/Function - Can Return Value.html new file mode 100644 index 0000000..878ec6d --- /dev/null +++ b/sel-blocksTests/Function - Can Return Value.html @@ -0,0 +1,41 @@ + + + + + + +Function - Can Return Value + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Function - Can Return Value
functionreturnsValue
return"banana"
endFunction
callreturnsValue
assertEval"${_result}" === "banana"true
+ + diff --git a/sel-blocksTests/GlobalFunctions 2.html b/sel-blocksTests/GlobalFunctions 2.html new file mode 100644 index 0000000..80832c9 --- /dev/null +++ b/sel-blocksTests/GlobalFunctions 2.html @@ -0,0 +1,46 @@ + + + + + + +GlobalFunctions 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
GlobalFunctions 2
functiondoStuff
openhttps://github.com/
openhttp://en.wikipedia.org/wiki/Chili
endFunction
calldoStuff
assertLocationhttp://en.wikipedia.org/wiki/Chili
+ + diff --git a/sel-blocksTests/GlobalFunctions.html b/sel-blocksTests/GlobalFunctions.html new file mode 100644 index 0000000..adcc056 --- /dev/null +++ b/sel-blocksTests/GlobalFunctions.html @@ -0,0 +1,65 @@ + + + + + +GlobalFunctions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
functions
functionsetGlobalVar
openhttp://www.google.com
getEvalglobalStoredVars.aGlobalVar = "set";
openhttp://www.yahoo.com
endFunction
getEvalglobalStoredVars.aGlobalVar = "reset";
assertNotEvalglobalStoredVars.aGlobalVar;set
assertEvalglobalStoredVars.aGlobalVar;reset
callsetGlobalVar
assertEvalglobalStoredVars.aGlobalVar;set
+ + diff --git a/sel-blocksTests/GlobalFunctionsTestSuite.html b/sel-blocksTests/GlobalFunctionsTestSuite.html new file mode 100644 index 0000000..c171f0e --- /dev/null +++ b/sel-blocksTests/GlobalFunctionsTestSuite.html @@ -0,0 +1,27 @@ + + + + + + Test Suite + + + + + + + + + + + + + + + + + + +
Test Suite
CreateGlobalVars
GlobalFunctions
GlobalFunctions 2
CallGlobalFunction
DefineFunctionParameters - Base
DefineFunctionParameters - With Default Values
StoreLocal - Function Scope
StoreGlobal - Function Scope
StoreGlobal - While Scope
StoreLocal - While Scope
Store - Behaves as StoreLocal
Function - Can Return Value
StoreAt - Function Scope Nesting
StoreAt - While Scope Nesting
+ + diff --git a/sel-blocksTests/Store - Behaves as StoreLocal.html b/sel-blocksTests/Store - Behaves as StoreLocal.html new file mode 100644 index 0000000..a917370 --- /dev/null +++ b/sel-blocksTests/Store - Behaves as StoreLocal.html @@ -0,0 +1,101 @@ + + + + + + +Store - Behaves as StoreLocal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Store - Behaves as StoreLocal
functionblockScopeVars
storethis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + diff --git a/sel-blocksTests/StoreAt - Function Scope Nesting.html b/sel-blocksTests/StoreAt - Function Scope Nesting.html new file mode 100644 index 0000000..d428d44 --- /dev/null +++ b/sel-blocksTests/StoreAt - Function Scope Nesting.html @@ -0,0 +1,129 @@ + + + + + + +StoreAt - Function Scope Nesting + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreAt - Function Scope Nesting
functionstorel
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
endFunction
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
callstorel
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ + diff --git a/sel-blocksTests/StoreAt - While Scope Nesting.html b/sel-blocksTests/StoreAt - While Scope Nesting.html new file mode 100644 index 0000000..7185ae6 --- /dev/null +++ b/sel-blocksTests/StoreAt - While Scope Nesting.html @@ -0,0 +1,140 @@ + + + + + + +StoreAt - While Scope Nesting + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreAt - While Scope Nesting
getEvalstoredVarsGlobal.notDefined = null
assertEvalstoredVarsGlobal.notDefined === nulltrue
getEvalstoredVarsGlobal.l = null;
assertEvalstoredVarsGlobal.l === null;true
storeLocalexists in parentl
assertEvalstoredVars.l === "exists in parent";true
storeLocal3x
whilex !== 0
storeAtthis ends up globalnotDefined
storeAtthis is stored in an ancestorl
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
storeEvalLocalx -= 1
endWhile
deleteVarx
assertEvalstoredVarsGlobal.notDefined === "this ends up global"true
assertEvalstoredVarsGlobal.l === "this is stored in an ancestor"false
assertEvalstoredVars.l === "this is stored in an ancestor"true
assertEvalstoredVarsLocal.l === "this is stored in an ancestor"true
assertEval"${l}" === "this is stored in an ancestor"true
+ + diff --git a/sel-blocksTests/StoreGlobal - Function Scope.html b/sel-blocksTests/StoreGlobal - Function Scope.html new file mode 100644 index 0000000..5c61fc5 --- /dev/null +++ b/sel-blocksTests/StoreGlobal - Function Scope.html @@ -0,0 +1,89 @@ + + + + + + +StoreGlobal - Function Scope + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - Function Scope
functionblockScopeVars
storeGlobalthis is stored globallyg
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endFunction
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + diff --git a/sel-blocksTests/StoreGlobal - While Scope.html b/sel-blocksTests/StoreGlobal - While Scope.html new file mode 100644 index 0000000..80d8560 --- /dev/null +++ b/sel-blocksTests/StoreGlobal - While Scope.html @@ -0,0 +1,95 @@ + + + + + + +StoreGlobal - While Scope + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreGlobal - While Scope
getEvalstoredVarsGlobal.g = null;
assertEvalstoredVarsGlobal.g === null;true
store1i
whilei > 0
store0i
storeGlobalthis is stored globallyg
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
endWhile
assertEvalstoredVarsGlobal.g === "this is stored globally"true
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVarsLocal.g === "this is stored globally"true
assertEval"${g}" === "this is stored globally"true
+ + diff --git a/sel-blocksTests/StoreLocal - Base.html b/sel-blocksTests/StoreLocal - Base.html new file mode 100644 index 0000000..cca78b6 --- /dev/null +++ b/sel-blocksTests/StoreLocal - Base.html @@ -0,0 +1,62 @@ + + + + + + +StoreLocal - Base + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - Base
functionblockScopeVars
storethis is stored globallyg
storeLocalthis is stored locallyl
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVars.l === "this is stored locally"true
endFunction
callblockScopeVars
assertEvalstoredVars.g === "this is stored globally"true
assertEvalstoredVars.l === "this is stored locally"false
+ + diff --git a/sel-blocksTests/StoreLocal - Function Scope.html b/sel-blocksTests/StoreLocal - Function Scope.html new file mode 100644 index 0000000..944f809 --- /dev/null +++ b/sel-blocksTests/StoreLocal - Function Scope.html @@ -0,0 +1,101 @@ + + + + + + +StoreLocal - Base + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - Base
functionblockScopeVars
storeLocalthis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endFunction
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
callblockScopeVars
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + diff --git a/sel-blocksTests/StoreLocal - While Scope.html b/sel-blocksTests/StoreLocal - While Scope.html new file mode 100644 index 0000000..cf71f8f --- /dev/null +++ b/sel-blocksTests/StoreLocal - While Scope.html @@ -0,0 +1,107 @@ + + + + + + +StoreLocal - While Scope + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StoreLocal - While Scope
getEvalstoredVarsGlobal.l = null;
getEvalstoredVars.l = null;
assertEvalstoredVars.l === null;true
assertEvalstoredVarsGlobal.l === null;true
store1i
whilei > 0
store0i
storeLocalthis is stored locallyl
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"true
assertEvalstoredVarsLocal.l === "this is stored locally"true
assertEval"${l}" === "this is stored locally"true
endWhile
assertEvalstoredVarsGlobal.l === "this is stored locally"false
assertEvalstoredVars.l === "this is stored locally"false
assertEvalstoredVarsLocal.l === "this is stored locally"false
assertEval"${l}" === "this is stored locally"false
+ + diff --git a/sel-blocksTests/_SelBlocks-TestSuite.html b/sel-blocksTests/_SelBlocks-TestSuite.html index 27faa8c..5cdf498 100644 --- a/sel-blocksTests/_SelBlocks-TestSuite.html +++ b/sel-blocksTests/_SelBlocks-TestSuite.html @@ -12,7 +12,28 @@ eval branching if -try +try - noop +try - finally with no error +try - catch but no error +try - catch specific error +try - catch specific error then finally +try - catch throw finally throw +try - bubble up to catch ALL +try - bubble up to catch ALL via finally +try - bubble up out of noop try to catch specific error +try - bubble up to catch specific error +try - bubble up to catch specific error via finally +try - throw catch rethrow +try - bubble out of nested function calls +try - command bubbling break with finally +try - command bubbling intra try break +try - command bubbling continue with finally +try - command bubbling intra try continue +try - command bubbling error replaced by return +try - command bubbling error replaced by return 2 +try - command bubbling return replaced by error +try - exitTest with finally processing +try - try without matching catch while for foreach diff --git a/sel-blocksTests/function.html b/sel-blocksTests/function.html index 5642472..22c8074 100644 --- a/sel-blocksTests/function.html +++ b/sel-blocksTests/function.html @@ -11,20 +11,15 @@ subtest - - resetEmitted - - - deleteVars sname, srole - emit - "START ${sname} ${srole}" - + assertEval + "START ${sname} ${srole}" === "START $" + "{sname} $" + "{srole}" + true @@ -32,6 +27,16 @@ doSomething sname = "dilbert,Q", srole = "goof" + + assertEval + "${_result}" === "sname=dilbert,Q,srole=goof" + true + + + deleteVars + sname, srole + + function @@ -39,7 +44,7 @@ sname - emit + return "sname=${sname},srole=${srole}" @@ -49,16 +54,41 @@ + + deleteVars + sname, srole + + call doSomething sname = "dogbert", srole = "woof" + + assertEval + "${_result}" === "sname=dogbert,srole=woof" + true + + + deleteVars + sname, srole + + call doSomething sname = "ratbert", srole = "squeak" + + assertEval + "${_result}" === "sname=ratbert,srole=squeak" + true + + + deleteVars + sname, srole + + foreach @@ -71,21 +101,25 @@ sname = sname, srole = "super=user" - endForeach - - + assertEval + "${_result}" === "sname=${sname},srole=super=user" + true - emit - "DONE ${sname} ${srole}" + deleteVars + sname, srole - - assertEmitted - "START $" + "{sname} $" + "{srole}~sname=dilbert,Q,srole=goof~sname=dogbert,srole=woof~sname=ratbert,srole=squeak~sname=asok,srole=super=user~sname=alice,srole=super=user~DONE $" + "{sname} $" + "{srole}" + endForeach + + + assertEval + "DONE ${sname} ${srole}" === "DONE $" + "{sname} $" + "{srole}" + true + @@ -100,8 +134,8 @@ - resetEmitted - + deleteVars + sname, srole @@ -110,7 +144,7 @@ sname - emit + return "sname=${sname},srole=${srole}" @@ -125,8 +159,13 @@ sname = "wally", srole = "lazy" - assertEmitted - "sname=wally,srole=lazy" + assertEval + "${_result}" === "sname=wally,srole=lazy" + true + + + deleteVars + sname, srole diff --git a/sel-blocksTests/nested-loops.html b/sel-blocksTests/nested-loops.html index b682354..b2c623d 100644 --- a/sel-blocksTests/nested-loops.html +++ b/sel-blocksTests/nested-loops.html @@ -119,7 +119,7 @@ assertEmitted - "START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 0" + "START 2~while=2~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~while=1~foreach=dilbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~foreach=dogbert~FOR=2~for=7~for=8~FOR=3~for=7~for=8~endFor ${n}~END 2" diff --git a/sel-blocksTests/try - bubble out of nested function calls.html b/sel-blocksTests/try - bubble out of nested function calls.html new file mode 100644 index 0000000..bd12a70 --- /dev/null +++ b/sel-blocksTests/try - bubble out of nested function calls.html @@ -0,0 +1,180 @@ + + + + + + +try - bubble out of nested function calls + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble out of nested function calls
log"-- bubble out of nested function calls --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-invoke
emit"trying"
emit"calling"
callsubBubn = 0
assertEval"this command should not be reached, due error thrown in function"
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-invoke
assertEvalselblocks.tcf.nestingLevel-1
functionsubBubn
trytcf-inner
emit"${n}) trying-inner"
ifn < 2
emit"${n}) calling"
callsubBubn = n+1
else
emit"${n}) throwing"
throw"blamo"
endIf
finally
emit"${n}) finally"
endTrytcf-inner
assertEvalselblocks.tcf.nestingLevel0
endFunction
emit"/])"
assertEmitted"([/~trying~calling~0) trying-inner~0) calling~1) trying-inner~1) calling~2) trying-inner~2) throwing~2) finally~1) finally~0) finally~caught 'blamo'~finally~/])"
+ + diff --git a/sel-blocksTests/try - bubble up out of noop try to catch specific error.html b/sel-blocksTests/try - bubble up out of noop try to catch specific error.html new file mode 100644 index 0000000..aee57d7 --- /dev/null +++ b/sel-blocksTests/try - bubble up out of noop try to catch specific error.html @@ -0,0 +1,131 @@ + + + + + + +try - bubble up out of noop try to catch specific error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up out of noop try to catch specific error
log"-- bubble out of no-op try to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trynoop-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
tryop-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
endTryop-inner
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrynoop-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~caught 'blamo'~finally~/])"
+ + diff --git a/sel-blocksTests/try - bubble up to catch ALL via finally.html b/sel-blocksTests/try - bubble up to catch ALL via finally.html new file mode 100644 index 0000000..bb14827 --- /dev/null +++ b/sel-blocksTests/try - bubble up to catch ALL via finally.html @@ -0,0 +1,136 @@ + + + + + + +try - bubble up to catch ALL via finally + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch ALL via finally
log"-- bubble up to catch ALL via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-allfin-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
tryt-allfin-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-allfin-inner
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-allfin-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~finally~caught-outer 'blamo try-catch-finally'~/])"
+ + diff --git a/sel-blocksTests/try - bubble up to catch ALL.html b/sel-blocksTests/try - bubble up to catch ALL.html new file mode 100644 index 0000000..4a92a44 --- /dev/null +++ b/sel-blocksTests/try - bubble up to catch ALL.html @@ -0,0 +1,126 @@ + + + + + + +try - bubble up to catch ALL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch ALL
log"-- bubble up to catch ALL --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-all-outer
emit"trying-outer"
assertEvalselblocks.tcf.nestingLevel0
tryt-all-inner
emit"trying"
throw"blamo try-catch-finally"
assertEval"this command should not be reached, due to throw"
catch/will NOT catch it/
emit"caught '" + _error.message + "'"
endTryt-all-inner
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught-outer '" + _error.message + "'"
endTryt-all-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying-outer~trying~caught-outer 'blamo try-catch-finally'~/])"
+ + diff --git a/sel-blocksTests/try - bubble up to catch specific error via finally.html b/sel-blocksTests/try - bubble up to catch specific error via finally.html new file mode 100644 index 0000000..ce43952 --- /dev/null +++ b/sel-blocksTests/try - bubble up to catch specific error via finally.html @@ -0,0 +1,141 @@ + + + + + + +try - bubble up to catch specific error via finally + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch specific error via finally
log"-- bubble up to catch specific error via finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
catch/blamo/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTrybub-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~finally~/])"
+ + diff --git a/sel-blocksTests/try - bubble up to catch specific error.html b/sel-blocksTests/try - bubble up to catch specific error.html new file mode 100644 index 0000000..a7af661 --- /dev/null +++ b/sel-blocksTests/try - bubble up to catch specific error.html @@ -0,0 +1,131 @@ + + + + + + +try - bubble up to catch specific error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - bubble up to catch specific error
log"-- bubble up to catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybub-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
trybub-spec-inner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing inner"
throw"blamo"
assertEval"this command should not be reached, due to throw"
finally
emit"finally"
endTrybub-spec-inner
catch/blamo/
emit"caught '" + _error.message + "'"
endTrybub-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing inner~finally~caught 'blamo'~/])"
+ + diff --git a/sel-blocksTests/try - catch but no error.html b/sel-blocksTests/try - catch but no error.html new file mode 100644 index 0000000..86c37a3 --- /dev/null +++ b/sel-blocksTests/try - catch but no error.html @@ -0,0 +1,79 @@ + + + + + + +try - catch but no error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch but no error
log"-- try/catch, but no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytc0
emit"trying"
catch
assertEval"should NEVER enter this catch block due to no error"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ + diff --git a/sel-blocksTests/try - catch specific error then finally.html b/sel-blocksTests/try - catch specific error then finally.html new file mode 100644 index 0000000..bc7c505 --- /dev/null +++ b/sel-blocksTests/try - catch specific error then finally.html @@ -0,0 +1,136 @@ + + + + + + +try - catch specific error then finally + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch specific error then finally
log"-- catch specific error, then finally --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-spec-outer
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel-1
emit"([/"
tryt-spec-inner
emit"trying inner"
throw"blamo inner"
assertEval"this command should not be reached, due to throw"
catch/blamo inner/
emit"caught '" + _error.message + "'"
finally
emit"finally"
endTryt-spec-inner
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
endTryt-spec-outer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~([/~trying inner~caught 'blamo inner'~finally~/])~/])"
+ + diff --git a/sel-blocksTests/try - catch specific error.html b/sel-blocksTests/try - catch specific error.html new file mode 100644 index 0000000..ce15200 --- /dev/null +++ b/sel-blocksTests/try - catch specific error.html @@ -0,0 +1,84 @@ + + + + + + +try - catch specific error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch specific error
log"-- catch specific error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytc1
throw"blamo catch ALL"
assertEval"this command should not be reached, due to thrown"
catch
emit"caught '" + _error.message + "'"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~caught 'blamo catch ALL'~/])"
+ + diff --git a/sel-blocksTests/try - catch throw finally throw.html b/sel-blocksTests/try - catch throw finally throw.html new file mode 100644 index 0000000..cb152ec --- /dev/null +++ b/sel-blocksTests/try - catch throw finally throw.html @@ -0,0 +1,156 @@ + + + + + + +try - catch throw finally throw + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - catch throw finally throw
log"-- catch/throw, finally/throw --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trytcf-trap
assertEvalselblocks.tcf.nestingLevel0
trytcf
emit"trying"
emit"throwing A"
throw"blamoA"
assertEval"this command should not be reached, due to thrown"
catch/blamoA/
emit"caught '" + _error.message + "'"
emit"throwing B"
throw"blamoB"
finally
emit"finally"
emit"throwing C"
throw"blamoC"
endTry
assertEvalselblocks.tcf.nestingLevel0
catch
emit"caught '" + _error.message + "'"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~throwing A~caught 'blamoA'~throwing B~finally~throwing C~caught 'blamoC'~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling break with finally.html b/sel-blocksTests/try - command bubbling break with finally.html new file mode 100644 index 0000000..4bd08df --- /dev/null +++ b/sel-blocksTests/try - command bubbling break with finally.html @@ -0,0 +1,119 @@ + + + + + + +try - command bubbling, break with finally + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling, break with finally
log"-- command bubbling, break w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
trybreaker
emit"${w}) trying"
ifw==2
emit"${w}) BREAK"
break
endIf
finally
emit"${w}) finallying"
endTrybreaker
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) BREAK~2) finallying~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling continue with finally.html b/sel-blocksTests/try - command bubbling continue with finally.html new file mode 100644 index 0000000..1841938 --- /dev/null +++ b/sel-blocksTests/try - command bubbling continue with finally.html @@ -0,0 +1,119 @@ + + + + + + +try - command bubbling continue with finally + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling continue with finally
log"-- command bubbling, continue w/finally --"
resetEmitted
emit"([/"
emit"while'g"
forw=3; w > 0; w--
assertEvalselblocks.tcf.nestingLevel-1
trycontinuer
emit"${w}) trying"
ifw==2
emit"${w}) CONTINUE"
continue
endIf
finally
emit"${w}) finallying"
endTrycontinuer
assertEvalselblocks.tcf.nestingLevel-1
emit"${w}) iterating"
endFor
emit"/])"
assertEmitted"([/~while'g~3) trying~3) finallying~3) iterating~2) trying~2) CONTINUE~2) finallying~1) trying~1) finallying~1) iterating~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling error replaced by return 2.html b/sel-blocksTests/try - command bubbling error replaced by return 2.html new file mode 100644 index 0000000..cf8f5f3 --- /dev/null +++ b/sel-blocksTests/try - command bubbling error replaced by return 2.html @@ -0,0 +1,129 @@ + + + + + + +try - command bubbling error replaced by return 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling error replaced by return 2
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubB
emit"returned ${_result}"
functioncmdBubB
emit"in cmdBubB"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf
emit"trying"
emit"throwing"
throw"short-lived error"
finally
emit"finallying"
emit"returning (2)"
return2
endTry
assertEval"this command should not be reached, due to throw/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubB~trying~throwing~finallying~returning (2)~returned 2~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling error replaced by return.html b/sel-blocksTests/try - command bubbling error replaced by return.html new file mode 100644 index 0000000..6d1428a --- /dev/null +++ b/sel-blocksTests/try - command bubbling error replaced by return.html @@ -0,0 +1,129 @@ + + + + + + +try - command bubbling error replaced by return + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling error replaced by return
log"-- command bubbling, error replaced by return --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubA
emit"returned ${_result}"
functioncmdBubA
emit"in cmdBubA"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"returning (2)"
return2
endTry
assertEval"this command should not be reached, due to return/return above"
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubA~trying~returning (1)~finallying~returning (2)~returned 2~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling intra try break.html b/sel-blocksTests/try - command bubbling intra try break.html new file mode 100644 index 0000000..fa9d2fa --- /dev/null +++ b/sel-blocksTests/try - command bubbling intra try break.html @@ -0,0 +1,119 @@ + + + + + + +try - command bubbling intra try break + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling intra try break
log"-- command bubbling, intra-try break --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trybreaker
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) BREAK"
break
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrybreaker
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) BREAK~finallying~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling intra try continue.html b/sel-blocksTests/try - command bubbling intra try continue.html new file mode 100644 index 0000000..b135e67 --- /dev/null +++ b/sel-blocksTests/try - command bubbling intra try continue.html @@ -0,0 +1,119 @@ + + + + + + +try - command bubbling intra try continue + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling intra try continue
log"-- command bubbling, intra-try continue --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
trycontinuer
emit"trying"
emit"while'g"
forw=3; w > 0; w--
ifw==2
emit"${w}) CONTINUE"
continue
endIf
emit"${w}) iterating"
endFor
finally
emit"finallying"
endTrycontinuer
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~while'g~3) iterating~2) CONTINUE~1) iterating~finallying~/])"
+ + diff --git a/sel-blocksTests/try - command bubbling return replaced by error.html b/sel-blocksTests/try - command bubbling return replaced by error.html new file mode 100644 index 0000000..139c160 --- /dev/null +++ b/sel-blocksTests/try - command bubbling return replaced by error.html @@ -0,0 +1,155 @@ + + + + + + +try - command bubbling return replaced by error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - command bubbling return replaced by error
log"-- command bubbling, return replaced by error --"
resetEmitted
emit"([/"
emit"calling"
callcmdBubC
emit"returned ${_result}"
functioncmdBubC
emit"in cmdBubC"
assertEvalselblocks.tcf.nestingLevel-1
trycmdBub-tcf-guardrail
assertEvalselblocks.tcf.nestingLevel0
trycmdBub-tcf
emit"trying"
emit"returning (1)"
return1
finally
emit"finallying"
emit"throwing"
throw"this-error-replaces-return-1"
endTry
catch/this-error-replaces-return-1/
emit"caught '" + _error.message + "'"
assertEvalselblocks.tcf.nestingLevel0
endTry
endFunction
emit"/])"
assertEmitted"([/~calling~in cmdBubC~trying~returning (1)~finallying~throwing~caught 'this-error-replaces-return-1'~returned ${_result}~/])"
+ + diff --git a/sel-blocksTests/try - exitTest with finally processing.html b/sel-blocksTests/try - exitTest with finally processing.html new file mode 100644 index 0000000..a7f0082 --- /dev/null +++ b/sel-blocksTests/try - exitTest with finally processing.html @@ -0,0 +1,89 @@ + + + + + + +try - exitTest with finally processing + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - exitTest with finally processing
log"-- exitTest w/finally processing --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryabort
emit"trying"
emit"exitTest ..."
exitTest
finally
emit"finallying"
assertEmitted"([/~trying~exitTest ...~finallying"
resetEmitted
endTryabort
assertEval"this command should not be reached, due to exitTest above"
+ + diff --git a/sel-blocksTests/try - finally with no error.html b/sel-blocksTests/try - finally with no error.html new file mode 100644 index 0000000..ec93f97 --- /dev/null +++ b/sel-blocksTests/try - finally with no error.html @@ -0,0 +1,79 @@ + + + + + + +try - finally with no error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - finally with no error
log"-- try/finally, w/no error --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-fin
emit"trying"
finally
emit"finally"
endTry
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~finally~/])"
+ + diff --git a/sel-blocksTests/try - noop.html b/sel-blocksTests/try - noop.html new file mode 100644 index 0000000..a6cb6e9 --- /dev/null +++ b/sel-blocksTests/try - noop.html @@ -0,0 +1,69 @@ + + + + + + +try - noop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - noop
log"-- no-op try --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryt-noop
emit"trying"
endTryt-noop
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying~/])"
+ + diff --git a/sel-blocksTests/try - throw catch rethrow.html b/sel-blocksTests/try - throw catch rethrow.html new file mode 100644 index 0000000..3674a70 --- /dev/null +++ b/sel-blocksTests/try - throw catch rethrow.html @@ -0,0 +1,141 @@ + + + + + + +try - throw catch rethrow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - throw catch rethrow
log"-- throw, catch, rethrow --"
resetEmitted
emit"([/"
assertEvalselblocks.tcf.nestingLevel-1
tryouter
emit"trying outer"
assertEvalselblocks.tcf.nestingLevel0
tryinner
emit"trying inner"
assertEvalselblocks.tcf.nestingLevel1
emit"throwing blamo1"
throw"blamo1"
assertEval"this command should not be reached, due to throw"
catch/blamo1/
emit"caught '" + _error.message + "'"
emit"throwing blamo2"
throw"blamo2"
endTryinner
catch/blamo2/
emit"caught '" + _error.message + "'"
endTryouter
assertEvalselblocks.tcf.nestingLevel-1
emit"/])"
assertEmitted"([/~trying outer~trying inner~throwing blamo1~caught 'blamo1'~throwing blamo2~caught 'blamo2'~/])"
+ + diff --git a/sel-blocksTests/try - try without matching catch.html b/sel-blocksTests/try - try without matching catch.html new file mode 100644 index 0000000..d4edc36 --- /dev/null +++ b/sel-blocksTests/try - try without matching catch.html @@ -0,0 +1,89 @@ + + + + + + +try - try without matching catch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
try - try without matching catch
log"-- try without matching catch --"
resetEmitted
assertEvalselblocks.tcf.nestingLevel-1
trymiss
assertEvaltruetrue
throw"blamo will NOT be caught at all"
assertEval"this command should not be reached"
catch/will NOT catch it/
log"caught miss '" + _error.message + "'"
finally
log"finally"
endTrymiss
assertEvalselblocks.tcf.nestingLevel-1
emit"trying"
+ + diff --git a/sel-blocksTests/while.html b/sel-blocksTests/while.html index f3178df..beb7b20 100644 --- a/sel-blocksTests/while.html +++ b/sel-blocksTests/while.html @@ -76,7 +76,7 @@ assertEmitted - "START: 3~iter=3~iter=2~iter=1~END: 0" + "START: 3~iter=3~iter=2~iter=1~END: 3"