diff --git a/docs/components.md b/docs/components.md index be796464..712cfe5e 100644 --- a/docs/components.md +++ b/docs/components.md @@ -137,10 +137,12 @@ dashboard.controller = function() { dashboard.view = function(ctrl) { return m("#example", [ - new autocompleter.view(ctrl.autocompleter, {onchange: m.withAttr("value", console.log)}), + new autocompleter.view(ctrl.autocompleter, {onchange: m.withAttr("value", log)}), ]); }; +//an FP-friendly console.log +var log = function(value) {console.log(value)} //initialize diff --git a/docs/how-to-read-signatures.md b/docs/how-to-read-signatures.md index 785bb6c6..fc794466 100644 --- a/docs/how-to-read-signatures.md +++ b/docs/how-to-read-signatures.md @@ -164,3 +164,13 @@ void test(Object { any | void config(DOMElement) } value) //example of a valid function call test({ first: "first", config: function(element) { /*do stuff*/ } }) ``` + +### Nullable Types + +A question mark `?` after a type denotes that a value can be either of that type or `undefined`. + +```clink +XMLHttpRequest? config() +``` + +In the example above, the `config` function is expected to return either an instance of the XMLHttpRequest object or `undefined` diff --git a/docs/mithril.deferred.md b/docs/mithril.deferred.md index e4b19d9c..48617e3c 100644 --- a/docs/mithril.deferred.md +++ b/docs/mithril.deferred.md @@ -136,14 +136,19 @@ For the most part, Mithril promises behave as you'd expect a [Promise/A+](http:/ Mithril promises forward a value downstream if a resolution callback returns `undefined`. This allows simpler debugging of promise chains: ```javascript +//a FP-friendly console.log +var log = function(value) { + console.log(value) +} + var data = m.request({method: "GET", url: "/data"}) - .then(console.log) //Mithril promises let us debug like this + .then(log) //Mithril promises let us debug like this .then(doStuff) var data = m.request({method: "GET", url: "/data"}) - .then(function(value) { // Promises/A+ would require us to declare an anonymous function + .then(function(value) { console.log(value) // here's the debugging snippet - return value // and we need to remember to return the value as well + return value // Promises/A+ requires us to return a value }) .then(doStuff) // or else `doStuff` will break diff --git a/docs/mithril.request.md b/docs/mithril.request.md index 10230361..c1232418 100644 --- a/docs/mithril.request.md +++ b/docs/mithril.request.md @@ -139,8 +139,13 @@ As you saw, you can chain operations that act on the response data. Typically th In the example below, we take advantage of queuing to debug the AJAX response data prior to doing further processing on the user list ```javascript +//a FP-friendly console.log +var log = function(value) { + console.log(value) +} + var users = m.request({method: "GET", url: "/user"}) - .then(console.log); + .then(log); .then(function(users) { //add one more user to the response return users.concat({name: "Jane"}) diff --git a/docs/tools.md b/docs/tools.md index ce2fe847..cd325b63 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -57,11 +57,11 @@ You can use it by adding a reference to your Typescript files. This will allow t ### Internet Explorer Compatibility -Mithril relies on some Ecmascript 5 features, namely: `Array::indexOf` and `Object::keys`, as well as the `JSON` object. +Mithril relies on some Ecmascript 5 features, namely: `Array::indexOf`, `Object::keys` and `Function::bind`, as well as the `JSON` object. You can use polyfill libraries to support these features in IE7. -- [ES5 Shim](https://github.com/es-shims/es5-shim) or Mozilla.org's [Array::indexOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) and [Object::keys](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) polyfills +- [ES5 Shim](https://github.com/es-shims/es5-shim) or Mozilla.org's [Array::indexOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf), [Object::keys](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) and [Function::bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfills - [JSON2.js](https://github.com/douglascrockford/JSON-js/blob/master/json2.js) diff --git a/mithril.closure-compiler-externs.js b/mithril.closure-compiler-externs.js new file mode 100644 index 00000000..ed3575ca --- /dev/null +++ b/mithril.closure-compiler-externs.js @@ -0,0 +1,15 @@ +var m = { + "render": function () {}, + "trust": function () {}, + "module": function () {}, + "redraw": function () {}, + "startComputation": function () {}, + "endComputation": function () {}, + "withAttr": function () {}, + "route": function () {}, + "prop": function () {}, + "deferred": function () {}, + "sync": function () {}, + "request": function () {}, + "deps": function () {} +} diff --git a/mithril.js b/mithril.js index 886b2e28..f429a659 100644 --- a/mithril.js +++ b/mithril.js @@ -4,7 +4,7 @@ Mithril = m = new function app(window, undefined) { function m() { var args = arguments - var hasAttrs = type.call(args[1]) == "[object Object]" && !("tag" in args[1]) && !("subtree" in args[1]) + var hasAttrs = args[1] !== undefined && type.call(args[1]) == "[object Object]" && !("tag" in args[1]) && !("subtree" in args[1]) var attrs = hasAttrs ? args[1] : {} var classAttrName = "class" in attrs ? "class" : "className" var cell = {tag: "div", attrs: {}} @@ -29,8 +29,7 @@ Mithril = m = new function app(window, undefined) { return cell } function build(parentElement, parentTag, parentCache, parentIndex, data, cached, shouldReattach, index, editable, namespace, configs) { - if (data === undefined) return undefined - if (data === null) data = "" + if (data === undefined || data === null) data = "" if (data.subtree === "retain") return cached var cachedType = type.call(cached), dataType = type.call(data) @@ -555,7 +554,7 @@ Mithril = m = new function app(window, undefined) { else next[method](result !== undefined ? result : value) } catch (e) { - if (e instanceof Error && e.constructor !== Error) throw e + if (type.call(e) == "[object Error]" && e.constructor !== Error) throw e else next.reject(e) } } @@ -587,9 +586,13 @@ Mithril = m = new function app(window, undefined) { var deferred = m.deferred() var outstanding = args.length var results = new Array(outstanding) - for (var i = 0; i < args.length; i++) { - args[i].then(synchronizer(i, true), synchronizer(i, false)) + if (args.length > 0) { + for (var i = 0; i < args.length; i++) { + args[i].then(synchronizer(i, true), synchronizer(i, false)) + } } + else deferred.resolve() + return deferred.promise } function identity(value) {return value} @@ -659,7 +662,7 @@ Mithril = m = new function app(window, undefined) { } catch (e) { if (e instanceof SyntaxError) throw new SyntaxError("Could not parse HTTP response. See http://lhorie.github.io/mithril/mithril.request.html#using-variable-data-formats") - else if (e instanceof Error && e.constructor !== Error) throw e + else if (type.call(e) == "[object Error]" && e.constructor !== Error) throw e else deferred.reject(e) } if (xhrOptions.background !== true) m.endComputation() diff --git a/tests/mithril-tests.js b/tests/mithril-tests.js index 7142e5ac..7e6ebbda 100644 --- a/tests/mithril-tests.js +++ b/tests/mithril-tests.js @@ -1517,6 +1517,11 @@ function testMithril(mock) { deferred1.resolve("test") return value[0] === "test" && value[1] === "foo" }) + test(function() { + var value = 1 + m.sync([]).then(function() {value = 2}) + return value == 2 + }) //m.startComputation/m.endComputation test(function() { @@ -1588,4 +1593,4 @@ if (typeof window != "undefined") { //mock testMithril(mock.window); -test.print(function(value){console.log(value)}); \ No newline at end of file +test.print(function(value) {console.log(value)})