Skip to content

Commit a32e2d8

Browse files
committed
v1.1.24 — release
1 parent 491360a commit a32e2d8

4 files changed

Lines changed: 54 additions & 24 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "wstp-node",
3-
"version": "1.1.23",
3+
"version": "1.1.24",
44
"description": "Native Node.js addon for Wolfram/Mathematica WSTP \u2014 kernel sessions with evaluation queue, streaming Print/messages, Dialog subsessions, and side-channel WstpReader",
55
"main": "build/Release/wstp.node",
66
"types": "index.d.ts",

src/drain.cc

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -673,17 +673,6 @@ EvalResult DrainToEvalResult(WSLINK lp, EvalOptions* opts) {
673673
DiagLog("[Drain] DrainToEvalResult entered, rejectDialog=" +
674674
std::to_string(opts ? opts->rejectDialog : false) +
675675
" interactive=" + std::to_string(opts ? opts->interactive : false));
676-
// Diagnostic: poll for 3s to see if kernel will ever respond
677-
for (int i = 0; i < 60; ++i) {
678-
if (WSReady(lp)) {
679-
DiagLog("[Drain] data arrived after " + std::to_string(i * 50) + "ms");
680-
break;
681-
}
682-
std::this_thread::sleep_for(std::chrono::milliseconds(50));
683-
}
684-
if (!WSReady(lp)) {
685-
DiagLog("[Drain] WARNING: no data from kernel after 3s poll");
686-
}
687676
EvalResult r;
688677

689678
// Parse "In[42]:=" → 42
@@ -752,8 +741,20 @@ EvalResult DrainToEvalResult(WSLINK lp, EvalOptions* opts) {
752741
while (sp < raw.size() && raw[sp] == ' ') ++sp;
753742
raw = raw.substr(sp);
754743
for (size_t i = 0; i < raw.size(); ) {
755-
if (raw.compare(i, 4, NL) == 0) { msg += ' '; i += 4; }
756-
else { msg += raw[i++]; }
744+
// Decode WL octal escapes: \NNN → actual byte (UTF-8 passthrough).
745+
// \012 (newline) is converted to space to keep lines compact.
746+
if (i + 3 < raw.size() && raw[i] == '\\' &&
747+
raw[i+1] >= '0' && raw[i+1] <= '7' &&
748+
raw[i+2] >= '0' && raw[i+2] <= '7' &&
749+
raw[i+3] >= '0' && raw[i+3] <= '7') {
750+
unsigned char byte =
751+
static_cast<unsigned char>((raw[i+1]-'0')*64 + (raw[i+2]-'0')*8 + (raw[i+3]-'0'));
752+
if (byte == 0x0A) msg += ' '; // newline → space
753+
else msg += static_cast<char>(byte);
754+
i += 4;
755+
} else {
756+
msg += raw[i++];
757+
}
757758
}
758759
// Both outer and dialog messages go onto r.messages.
759760
r.messages.push_back(msg);

src/wstp_expr.cc

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,26 @@ WExpr ReadExprRaw(WSLINK lp, int depth) {
3535
return e;
3636
}
3737
if (type == WSTKSTR) {
38-
const char* s = nullptr;
39-
if (!WSGetString(lp, &s))
40-
return WExpr::mkError("WSGetString failed");
41-
WExpr e; e.kind = WExpr::String; e.strVal = s;
42-
WSReleaseString(lp, s);
38+
// Use UTF-8 variant so Wolfram char escapes like \|01F605 and \[Alpha]
39+
// are decoded to actual UTF-8 bytes instead of being returned verbatim.
40+
const unsigned char* s = nullptr;
41+
int bytes = 0, chars = 0;
42+
if (!WSGetUTF8String(lp, &s, &bytes, &chars))
43+
return WExpr::mkError("WSGetUTF8String failed");
44+
WExpr e; e.kind = WExpr::String;
45+
e.strVal.assign(reinterpret_cast<const char*>(s), bytes);
46+
WSReleaseUTF8String(lp, s, bytes);
4347
return e;
4448
}
4549
if (type == WSTKSYM) {
46-
const char* s = nullptr;
47-
if (!WSGetSymbol(lp, &s))
48-
return WExpr::mkError("WSGetSymbol failed");
49-
WExpr e; e.kind = WExpr::Symbol; e.strVal = s;
50-
WSReleaseSymbol(lp, s);
50+
// UTF-8 variant — decodes \|NNNN / \[Name] into UTF-8 bytes.
51+
const unsigned char* s = nullptr;
52+
int bytes = 0, chars = 0;
53+
if (!WSGetUTF8Symbol(lp, &s, &bytes, &chars))
54+
return WExpr::mkError("WSGetUTF8Symbol failed");
55+
WExpr e; e.kind = WExpr::Symbol;
56+
e.strVal.assign(reinterpret_cast<const char*>(s), bytes);
57+
WSReleaseUTF8Symbol(lp, s, bytes);
5158
return e;
5259
}
5360
if (type == WSTKFUNC) {

tests/_test_rule.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const path = require('path');
2+
const addonPath = path.join(__dirname, '..', 'build', 'Release', 'wstp_addon.node');
3+
const wstp = require(addonPath);
4+
5+
const kernelPath = '/Applications/Wolfram 3.app/Contents/MacOS/WolframKernel';
6+
const client = new wstp.WstpClient(kernelPath);
7+
client.start();
8+
setTimeout(() => {
9+
client.evaluate('"\[Rule]" // ToCharacterCode', (r) => {
10+
console.log("Rule codepoint:", JSON.stringify(r));
11+
client.evaluate('ToString[MakeBoxes[a -> b, TraditionalForm], InputForm]', (r2) => {
12+
console.log("boxStr:", JSON.stringify(r2));
13+
const s = r2?.value ?? r2;
14+
// print hex of each character
15+
if (typeof s === 'string') {
16+
const buf = Buffer.from(s, 'utf8');
17+
console.log("hex:", buf.toString('hex'));
18+
}
19+
client.stop();
20+
});
21+
});
22+
}, 2000);

0 commit comments

Comments
 (0)