on master help sign in
Simplify the JS API for sending values to signal ports, making error handling more reasonable
996848cEvan Czaplicki
libraries/Native/Ports.js+26−15
@@ -7,18 +7,8 @@ Elm.Native.Ports.make = function(elm) {
7 var Signal = Elm.Signal.make(elm);
7 var Signal = Elm.Signal.make(elm);
8
8
9 function incomingSignal(converter) {
9 function incomingSignal(converter) {
10− return function(port) {
10+ converter.isSignal = true;
11− var base = converter(port.internal.defaultValue);
12− var signal = Signal.constant(base);
13− port.internal.subscribe(function(v) {
14− try {
15− elm.notify(signal.id, converter(v));
11+ return converter;
16− } catch(e) {
17− port.internal.errorHandler(v);
18− }
19− });
20− return signal;
21− }
22 }
12 }
23
13
24 function outgoingSignal(converter) {
14 function outgoingSignal(converter) {
@@ -42,18 +32,39 @@ Elm.Native.Ports.make = function(elm) {
42 }
32 }
43
33
44 function portIn(name, converter) {
34 function portIn(name, converter) {
45− var value = elm.ports.incoming[name];
35+ var jsValue = elm.ports.incoming[name];
46− if (!value) {
36+ if (jsValue === undefined) {
47 throw new Error("Initialization Error: port '" + name +
37 throw new Error("Initialization Error: port '" + name +
48 "' was not given an input!");
38 "' was not given an input!");
49 }
39 }
50 elm.ports.uses[name] += 1;
40 elm.ports.uses[name] += 1;
51 try {
41 try {
52− return converter(value);
42+ var elmValue = converter(jsValue);
53 } catch(e) {
43 } catch(e) {
54 throw new Error("Initialization Error on port '" + name + "': \n" + e.message);
44 throw new Error("Initialization Error on port '" + name + "': \n" + e.message);
55 }
45 }
46+
47+ // just return a static value if it is not a signal
48+ if (!converter.isSignal) {
49+ return elmValue;
50+ }
51+
52+ // create a signal if necessary
53+ var signal = Signal.constant(elmValue);
54+ function send(jsValue) {
55+ try {
56+ var elmValue = converter(jsValue);
57+ } catch(e) {
58+ throw new Error("Error sending to port '" + name + "': \n" + e.message);
59+ }
60+ setTimeout(function() {
61+ elm.notify(signal.id, elmValue);
62+ }, 0);
63+ }
64+ elm.ports.outgoing[name] = { send:send };
65+ return signal;
56 }
66 }
67+
57 function portOut(name, converter, value) {
68 function portOut(name, converter, value) {
58 try {
69 try {
59 elm.ports.outgoing[name] = converter(value);
70 elm.ports.outgoing[name] = converter(value);
runtime/Init.js−23
@@ -27,29 +27,6 @@ Elm.worker = function(module, ports) {
27 return init(ElmRuntime.Display.NONE, {}, module, ports || {});
27 return init(ElmRuntime.Display.NONE, {}, module, ports || {});
28};
28};
29
29
30−Elm.signal = function(defaultValue, errorHandler) {
31− var subscribers = []
32− function subscribe(handler) {
33− subscribers.push(handler);
34− }
35− function unsubscribe(handler) {
36− subscribers.pop(subscribers.indexOf(handler));
37− }
38− function send(value) {
39− var len = subscribers.length;
40− for (var i = 0; i < len; ++i) {
41− subscribers[i](value);
42− }
43− }
44− return {
45− send:send,
46− internal: { defaultValue:defaultValue,
47− errorHandler:errorHandler,
48− subscribe: subscribe,
49− unsubscribe: unsubscribe }
50− };
51−}
52−
53function init(display, container, module, ports, moduleToReplace) {
30function init(display, container, module, ports, moduleToReplace) {
54 // defining state needed for an instance of the Elm RTS
31 // defining state needed for an instance of the Elm RTS
55 var inputs = [];
32 var inputs = [];