11// EspruinoTools bundle (https://github.com/espruino/EspruinoTools)
22// Created with https://github.com/espruino/EspruinoWebIDE/blob/master/extras/create_espruinotools_js.sh
3- // Based on EspruinoWebIDE 0.79.12
3+ // Based on EspruinoWebIDE 0.79.14
44/**
55 Copyright 2014 Gordon Williams (gw@pur3.co.uk)
66
@@ -108,7 +108,10 @@ var Espruino;
108108 var n = 0;
109109 var cbCalled = false;
110110 var cb = function(inData) {
111- if (cbCalled) throw new Error("Internal error in "+eventType+" processor. Callback is called TWICE.");
111+ if (cbCalled) {
112+ throw new Error("Internal error in "+eventType+" processor. Callback is called TWICE.");
113+ return;
114+ }
112115 cbCalled = true;
113116 if (n < p.length) {
114117 cbCalled = false;
@@ -7167,6 +7170,7 @@ while (d!==undefined) {console.log(btoa(d));d=f.read(${CHUNKSIZE});}
71677170 case "true" : tok = lex.next(); return true;
71687171 case "false" : tok = lex.next(); return false;
71697172 case "null" : tok = lex.next(); return null;
7173+ case "NaN" : tok = lex.next(); return NaN;
71707174 }
71717175 if (tok.str == "[") {
71727176 tok = lex.next();
@@ -7677,6 +7681,7 @@ To add a new serial device, you must add an object to
76777681 // on("open", () => ... ) connection opened
76787682 // on("close", () => ... ) connection closed
76797683 // on("data", (data) => ... ) when data is received (as string)
7684+ // on("line", (line) => ... ) when a line of data is received (as string), uses /r OR /n for lines
76807685 // on("packet", (type,data) => ... ) when a packet is received (if .parsePackets=true)
76817686 // on("ack", () => ... ) when an ACK is received (if .parsePackets=true)
76827687 // on("nak", () => ... ) when an ACK is received (if .parsePackets=true)
@@ -7695,6 +7700,7 @@ To add a new serial device, you must add an object to
76957700 rxDataHandlerLastCh = 0; // used by rxDataHandler - last received character
76967701 rxDataHandlerPacket = undefined; // used by rxDataHandler - used for parsing
76977702 rxDataHandlerTimeout = undefined; // timeout for unfinished packet
7703+ rxLine = ""; // current partial line for on("line" event
76987704 progressAmt = 0; // When sending a file, how many bytes through are we?
76997705 progressMax = 0; // When sending a file, how long is it in bytes? 0 if not sending a file
77007706
@@ -7773,6 +7779,13 @@ To add a new serial device, you must add an object to
77737779 // forward any data
77747780 if (this.cb) this.cb(data);
77757781 this.emit('data', data);
7782+ // look for newlines and send out a 'line' event
7783+ let lines = (this.rxLine + data).split(/\r\n/);
7784+ while (lines.length>1)
7785+ this.emit('line', lines.shift());
7786+ this.rxLine = lines[0];
7787+ if (this.rxLine.length > 10000) // only store last 10k characters
7788+ this.rxLine = this.rxLine.slice(-10000);
77767789 }
77777790 }
77787791
@@ -7786,8 +7799,9 @@ To add a new serial device, you must add an object to
77867799 this.hadData = false;
77877800 this.flowControlWait = 0;
77887801 this.rxDataHandlerLastCh = 0;
7789- if (this.isOpen) {
7790- this.isOpen = false;
7802+ this.rxLine = "";
7803+ if (!this.isOpen) {
7804+ this.isOpen = true;
77917805 this.emit("open");
77927806 }
77937807 // if we had any writes queued, do them now
@@ -7796,12 +7810,12 @@ To add a new serial device, you must add an object to
77967810
77977811 /** Called when the connection is closed - resets any stored info/rejects promises */
77987812 closeHandler() {
7799- log(1, "Disconnected");
78007813 this.isOpening = false;
78017814 this.txInProgress = false;
78027815 this.txDataQueue = [];
78037816 this.hadData = false;
78047817 if (this.isOpen) {
7818+ log(1, "Disconnected");
78057819 this.isOpen = false;
78067820 this.emit("close");
78077821 }
@@ -8165,54 +8179,67 @@ To add a new serial device, you must add an object to
81658179 return oldListener;
81668180 };
81678181
8168- /* Calls 'callback(port_list, shouldCallAgain)'
8169- 'shouldCallAgain==true' means that more devices
8170- may appear later on (eg Bluetooth LE).*/
8171- var getPorts=function(callback) {
8172- var ports = [];
8173- var newPortToDevice = [];
8174- // get all devices
8175- var responses = 0;
8182+ /**
8183+ * List ports available over all configured devices.
8184+ * `shouldCallAgain` mean that more devices may appear later on (eg. Bluetooth LE)
8185+ * @param {(ports, shouldCallAgain) => void} callback
8186+ */
8187+ var getPorts = function (callback) {
8188+ var newPortToDevice = {};
8189+
81768190 var devices = Espruino.Core.Serial.devices;
8177- if (!devices || devices.length== 0) {
8178- portToDevice = newPortToDevice;
8191+ if (!devices || devices.length == 0) {
8192+ portToDevice = newPortToDevice;
81798193 return callback(ports, false);
81808194 }
8181- var shouldCallAgain = false;
8182- devices.forEach(function (device) {
8183- //console.log("getPorts -->",device.name);
8184- device.getPorts(function(devicePorts, instantPorts) {
8185- //console.log("getPorts <--",device.name);
8186- if (instantPorts===false) shouldCallAgain = true;
8187- if (devicePorts) {
8188- devicePorts.forEach(function(port) {
8189- var ignored = false;
8190- if (Espruino.Config.SERIAL_IGNORE)
8191- Espruino.Config.SERIAL_IGNORE.split("|").forEach(function(wildcard) {
8192- var regexp = "^"+wildcard.replace(/\./g,"\\.").replace(/\*/g,".*")+"$";
8193- if (port.path.match(new RegExp(regexp)))
8194- ignored = true;
8195- });
81968195
8197- if (!ignored) {
8198- if (port.usb && port.usb[0]==0x0483 && port.usb[1]==0x5740)
8199- port.description = "Espruino board";
8200- ports.push(port);
8201- newPortToDevice[port.path] = device;
8202- }
8203- });
8204- }
8205- responses++;
8206- if (responses == devices.length) {
8207- portToDevice = newPortToDevice;
8208- ports.sort(function(a,b) {
8196+ // Test to see if a given port path is ignore or not by configuration
8197+ function isIgnored(path) {
8198+ if (!Espruino.Config.SERIAL_IGNORE) return false;
8199+
8200+ return Espruino.Config.SERIAL_IGNORE.split("|").some((wildcard) => {
8201+ const regexp = new RegExp(
8202+ `^${wildcard.replace(/\./g, "\\.").replace(/\*/g, ".*")}$`
8203+ );
8204+
8205+ return path.match(regexp);
8206+ });
8207+ }
8208+
8209+ // Asynchronously call 'getPorts' on all devices and map results back as a series of promises
8210+ Promise.all(
8211+ devices.map((device) =>
8212+ new Promise((resolve) => device.getPorts(resolve)).then(
8213+ (devicePorts, instantPorts) => ({
8214+ device: device,
8215+ shouldCallAgain: !instantPorts, // If the ports are not present now (eg. BLE) then call again
8216+ value: (devicePorts || [])
8217+ .filter((port) => !isIgnored(port.path)) // Filter out all the ignored ports
8218+ .map((port) => {
8219+ // Map a description for this particular Product/Vendor
8220+ if (port.usb && port.usb[0] == 0x0483 && port.usb[1] == 0x5740)
8221+ port.description = "Espruino board";
8222+ return port;
8223+ }),
8224+ })
8225+ )
8226+ )
8227+ ).then((results) => {
8228+ portToDevice = results.reduce((acc, promise) => {
8229+ promise.value.forEach((port) => (acc[port.path] = promise.device));
8230+ return acc;
8231+ }, {});
8232+
8233+ callback(
8234+ results
8235+ .flatMap((result) => result.value)
8236+ .sort((a, b) => {
82098237 if (a.unimportant && !b.unimportant) return 1;
82108238 if (b.unimportant && !a.unimportant) return -1;
82118239 return 0;
8212- });
8213- callback(ports, shouldCallAgain);
8214- }
8215- });
8240+ }),
8241+ results.some((result) => result.shouldCallAgain),
8242+ );
82168243 });
82178244 };
82188245
@@ -8223,10 +8250,10 @@ To add a new serial device, you must add an object to
82238250
82248251 var openSerialInternal=function(serialPort, connectCallback, disconnectCallback, attempts) {
82258252 /* If openSerial is called, we need to have called getPorts first
8226- in order to figure out which one of the serial_ implementations
8227- we must call into. */
8253+ in order to figure out which one of the serial_ implementations
8254+ we must call into. */
82288255 if (portToDevice === undefined) {
8229- portToDevice = [] ; // stop recursive calls if something errors
8256+ portToDevice = {} ; // stop recursive calls if something errors
82308257 return getPorts(function() {
82318258 openSerialInternal(serialPort, connectCallback, disconnectCallback, attempts);
82328259 });
@@ -8332,9 +8359,8 @@ To add a new serial device, you must add an object to
83328359 * sent blocks to 512 because on Mac we seem to lose
83338360 * data otherwise (not on any other platforms!) */
83348361 if (slowWrite) blockSize=19;
8335- writeData.blockSize = blockSize;
83368362
8337- writeData.showStatus &= writeData.data.length>writeData. blockSize;
8363+ writeData.showStatus &= writeData.data.length>blockSize;
83388364 if (writeData.showStatus) {
83398365 Espruino.Core.Status.setStatus("Sending...", writeData.data.length);
83408366 console.log("serial: ---> "+JSON.stringify(writeData.data));
@@ -8371,12 +8397,13 @@ To add a new serial device, you must add an object to
83718397 }
83728398
83738399 let isLast = writeData.data.length == 0;
8374- // update status
8375- if (writeData.showStatus)
8376- Espruino.Core.Status.incrementProgress(d.length);
83778400 // actually write data
83788401 //console.log("serial: Sending block "+JSON.stringify(d)+", wait "+split.delay+"ms");
8402+ Espruino.Core.Serial.connection.chunkSize = blockSize;
83798403 Espruino.Core.Serial.connection.write(d, function() { // write data, but the callback returns a promise that delays
8404+ // update status
8405+ if (writeData.showStatus)
8406+ Espruino.Core.Status.incrementProgress(d.length);
83808407 return new Promise(resolve => setTimeout(function() {
83818408 if (isLast && writeData.showStatus) {
83828409 Espruino.Core.Status.setStatus("Sent");
@@ -8859,8 +8886,8 @@ To add a new serial device, you must add an object to
88598886 // if we needed to load something, wait until it's loaded before resolving this
88608887 Promise.all(newPromises).then(function(){
88618888 // add the module to end of our array
8862- if (Espruino.Config.MODULE_AS_FUNCTION)
8863- loadedModuleData.push("Modules.addCached(" + JSON.stringify(module.name) + ",function(){" + module.code + "\n });");
8889+ if (Espruino.Config.MODULE_AS_FUNCTION) // check for '//' is just in case, most minified modules shouldn't have it
8890+ loadedModuleData.push("Modules.addCached(" + JSON.stringify(module.name) + ",function(){" + module.code.trim() + (module.code.includes("//")?"\n":"") + " });");
88648891 else
88658892 loadedModuleData.push("Modules.addCached(" + JSON.stringify(module.name) + "," + JSON.stringify(module.code) + ");");
88668893 // We're done
@@ -37091,7 +37118,7 @@ global.esmangle = require('../lib/esmangle');
3709137118
3709237119 function minify(code, callback, level, isModule, description) {
3709337120 (function() {
37094- Espruino.Core.Status.setStatus("Minifying"+(isModule?description.substr(2) :""));
37121+ Espruino.Core.Status.setStatus("Minifying"+(isModule?description.substr(4)/*module name*/ :""));
3709537122 var _callback = callback;
3709637123 callback = function(code) {
3709737124 Espruino.Core.Status.setStatus("Minification complete");
@@ -37310,7 +37337,8 @@ global.esmangle = require('../lib/esmangle');
3731037337 resultCode += "\n";
3731137338 if (tok.str==")" || tok.str=="}" || tok.str=="]") brackets--;
3731237339 // if we have a token for something, use that - else use the string
37313- if (pretokeniseStrings && tok.type == "STRING") {
37340+ if (pretokeniseStrings && tok.type == "STRING" &&
37341+ tok.value.split("").reduce((r,ch) => r&&(ch.charCodeAt(0)<256), true)/*all 8 bit*/) {
3731437342 let str = tok.value; // get string value
3731537343 lastIdx = tok.endIdx; // get next token
3731637344 lastlastTok = lastTok;
0 commit comments