Skip to content

Commit 7502f4c

Browse files
committed
Fix issue caused by pretokenising of UTF8 strings (which get converted after the pretokenise step and cause the length to be wrong)
Even if length were correct, pretokenising the string stops the scan for UTF8 char patterns so the string wouldn't be treated correctly
1 parent 7e7475b commit 7502f4c

File tree

1 file changed

+86
-58
lines changed

1 file changed

+86
-58
lines changed

lib/espruinotools.js

Lines changed: 86 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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 ([email protected])
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

Comments
 (0)