diff --git a/js-assembler/runtime-src/baselib-lists.js b/js-assembler/runtime-src/baselib-lists.js index 9b0ba06..a4ad775 100644 --- a/js-assembler/runtime-src/baselib-lists.js +++ b/js-assembler/runtime-src/baselib-lists.js @@ -121,7 +121,7 @@ break; } } - if (p !== Empty.EMPTY) { + if (p !== EMPTY) { texts.push('.'); texts.push(baselib.format.toDisplayedString(p, cache)); } @@ -138,14 +138,14 @@ while (p instanceof Cons) { node.appendChild(baselib.format.toDomNode(p.first, cache)); p = p.rest; - if (p !== Empty.EMPTY) { + if (p !== EMPTY) { node.appendChild(document.createTextNode(" ")); } if (typeof (p) === 'object' && cache.containsKey(p)) { break; } } - if (p !== Empty.EMPTY) { + if (p !== EMPTY) { node.appendChild(document.createTextNode(".")); node.appendChild(document.createTextNode(" ")); node.appendChild(baselib.format.toDomNode(p, cache)); @@ -157,13 +157,13 @@ var isPair = function (x) { return x instanceof Cons; }; - var isEmpty = function (x) { return x === Empty.EMPTY; }; + var isEmpty = function (x) { return x === EMPTY; }; var makePair = Cons.makeInstance; var makeList = function () { - var result = Empty.EMPTY, i; + var result = EMPTY, i; for (i = arguments.length - 1; i >= 0; i--) { result = Cons.makeInstance(arguments[i], result); } @@ -171,10 +171,21 @@ }; + // Coerse a list back into a JavaScript array. + var listToArray = function(lst) { + var result = []; + while (lst !== EMPTY) { + result.push(lst.first); + lst = lst.rest; + } + return result; + }; + + // isList: Any -> Boolean // Returns true if x is a list (a chain of pairs terminated by EMPTY). var isList = function (x) { - while (x !== Empty.EMPTY) { + while (x !== EMPTY) { if (x instanceof Cons) { x = x.rest; } else { @@ -229,6 +240,6 @@ exports.reverse = reverse; exports.length = length; exports.listRef = listRef; - + exports.listToArray = listToArray; }(this.plt.baselib)); \ No newline at end of file diff --git a/web-world/js-impl.js b/web-world/js-impl.js index 5a4de6c..3717fe0 100644 --- a/web-world/js-impl.js +++ b/web-world/js-impl.js @@ -80,6 +80,8 @@ } }; + var EMPTY_PENDING_ACTIONS = plt.baselib.lists.EMPTY; + ////////////////////////////////////////////////////////////////////// // A MockView provides a functional interface to the DOM. It @@ -88,17 +90,25 @@ // freshness of the MockView. var MockView = function(cursor, pendingActions, eventHandlers, nonce) { this.cursor = cursor; + + // (listof (view -> void)) this.pendingActions = pendingActions; + this.eventHandlers = eventHandlers; this.nonce = nonce; }; var isMockView = plt.baselib.makeClassPredicate(MockView); + MockView.prototype.getPendingActions = function() { + return plt.baselib.lists.listToArray(this.pendingActions).reverse(); + }; + + MockView.prototype.act = function(actionForCursor, actionForEventHandlers, actionForReal) { if (arguments.length !== 3) { throw new Error("act: insufficient arguments"); } return new MockView(actionForCursor(this.cursor), - this.pendingActions.concat([actionForReal]), + plt.baselib.lists.makePair(actionForReal, this.pendingActions), actionForEventHandlers(this.eventHandlers), this.nonce); }; @@ -441,7 +451,7 @@ View.prototype.getMockAndResetFocus = function(nonce) { this.focus = this.top; return new MockView(domToCursor($(this.top).get(0)), - [], + EMPTY_PENDING_ACTIONS, this.eventHandlers.slice(0), nonce); }; @@ -512,14 +522,14 @@ } catch (exn1) { return onFail(exn1); } - return onSuccess(new MockView(domToCursor(dom.get(0)), [], [], undefined)); + return onSuccess(new MockView(domToCursor(dom.get(0)), EMPTY_PENDING_ACTIONS, [], undefined)); } else { try { dom = $(plt.baselib.format.toDomNode(x)); } catch (exn2) { return onFail(exn2); } - return onSuccess(new MockView(domToCursor(dom.get(0)), [], [], undefined)); + return onSuccess(new MockView(domToCursor(dom.get(0)), EMPTY_PENDING_ACTIONS, [], undefined)); } }; @@ -1086,7 +1096,7 @@ function(newMockView) { if (newMockView.nonce === nonce) { var i; - var actions = newMockView.pendingActions; + var actions = newMockView.getPendingActions(); for (i = 0; i < actions.length; i++) { actions[i](view); }