Skip to content

Commit 314c817

Browse files
committed
added tracing methods and improved error handling
1 parent ac13338 commit 314c817

File tree

6 files changed

+93
-14
lines changed

6 files changed

+93
-14
lines changed

index.html

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
<div class="container">
2929
<h4>JSPython development console</h4>
3030
<div id="editor">
31-
x = [["sd"]]
32-
x
33-
</div>
31+
[
32+
[12, 42]
33+
[22, 88]
34+
]</div>
3435
<button onclick="runInterpreter()">Run</button>
3536
<textarea id="result"></textarea>
3637
</div>
@@ -50,7 +51,7 @@ <h4>JSPython development console</h4>
5051
.addFunction('returnsPromise', a1 => new Promise((s, f) => { setTimeout(() => s(a1), 10) }))
5152
.addFunction('nullValue', () => { console.log(' ** invoked!!!'); return null })
5253
.evaluate(scripts, {str: "shdsd sd,sd d s ds d"});
53-
document.getElementById('result').value = typeof result === 'object' ? JSON.stringify(result) : result
54+
document.getElementById('result').value = typeof result === 'object' ? JSON.stringify(result, null, '\t') : result
5455
console.log('Result => ', result);
5556
} catch (err) {
5657
document.getElementById('result').value = err;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jspython-interpreter",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"description": "JSPython is a javascript implementation of Python language that runs within web browser or NodeJS environment",
55
"keywords": [
66
"python",

src/eval/eval.expression.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ export class EvalExpression {
106106
const items = Tokenizer.splitAll(innerJson, [',']).map(s => s.trim());
107107

108108
for (const item of items) {
109+
if(!item || !item.length) {
110+
throw Error('JSON Parsing error: Empty operation after comma');
111+
}
109112

110113
if (Array.isArray(parentObj)) {
111114
// handle array
@@ -114,7 +117,7 @@ export class EvalExpression {
114117
parseJsonItems(trimFirstAndLastItem(item), newItem)
115118
parentObj.push(newItem)
116119
} else if (item[0] === '[') {
117-
const newItem = {}
120+
const newItem: any[] = [];
118121
parseJsonItems(trimFirstAndLastItem(item), newItem)
119122
parentObj.push(newItem)
120123
} else {
@@ -177,14 +180,18 @@ export class EvalExpression {
177180

178181
for (const item of items) {
179182

183+
if(!item || !item.length) {
184+
throw Error('JSON Parsing error: Empty operation after comma');
185+
}
186+
180187
if (Array.isArray(parentObj)) {
181188
// handle array
182189
if (item[0] === '{') {
183190
const newItem = {}
184191
await parseJsonItemsAsync(trimFirstAndLastItem(item), newItem)
185192
parentObj.push(newItem)
186-
} else if (item[0] === '[') {
187-
const newItem = {}
193+
} else if (item[0] === '[') {
194+
const newItem: any[] = [];
188195
await parseJsonItemsAsync(trimFirstAndLastItem(item), newItem)
189196
parentObj.push(newItem)
190197
} else {

src/interpreter.spec.ts

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,7 @@ describe('Interpreter', () => {
14831483
})
14841484

14851485
it('JSON parsing error 1', async () => {
1486+
let msg = ""
14861487
try {
14871488
await e.evaluate(
14881489
`
@@ -1492,20 +1493,80 @@ describe('Interpreter', () => {
14921493
}
14931494
x
14941495
`);
1495-
expect(1).toBe(0); // should not come here
1496+
msg = "NO ERROR"
14961497
} catch (error) {
1497-
expect(1).toBe(1);
1498+
msg = "ERROR"
14981499
}
14991500

1501+
expect(msg).toBe("ERROR");
1502+
1503+
msg = "";
1504+
15001505
try {
15011506
await e.evaluate(`x = { p1: {} p2: 5 }`);
1502-
expect(1).toBe(0); // should not come here
1507+
msg = "NO ERROR"
15031508
} catch (error) {
1504-
expect(1).toBe(1);
1509+
msg = "ERROR"
15051510
}
15061511

1512+
expect(msg).toBe("ERROR");
15071513
})
15081514

1515+
it('JSON parsing Array of arrays', async () => {
1516+
let o = await e.evaluate(`[["ss", "ss2", 5]]`);
1517+
expect(o.length).toBe(1);
1518+
expect(o[0][1]).toBe("ss2");
1519+
expect(o[0][2]).toBe(5);
1520+
1521+
o = await e.evaluate(`[
1522+
["ss1", "ss21", 5],
1523+
["ss2", "ss22", 6],
1524+
["ss3", dateTime("2020-03-07"), 7],
1525+
[]
1526+
]`);
1527+
expect(o.length).toBe(4);
1528+
expect(o[0][1]).toBe("ss21");
1529+
expect(o[0][2]).toBe(5);
1530+
1531+
expect(o[1][1]).toBe("ss22");
1532+
expect(o[1][2]).toBe(6);
1533+
1534+
expect(o[2][1].toISOString()).toBe(new Date('2020-03-07').toISOString());
1535+
expect(o[3].length).toBe(0);
1536+
});
1537+
1538+
it('JSON parsing last comma error', async () => {
1539+
let x = ""
1540+
try {
1541+
await e.evaluate(`[[12, 42],`);
1542+
x = "NO ERROR"
1543+
} catch (error) {
1544+
x = "ERROR"
1545+
}
1546+
1547+
expect(x).toBe("ERROR");
1548+
1549+
x = ""
1550+
try {
1551+
await e.evaluate(`[
1552+
[12, 42],
1553+
]`);
1554+
x = "NO ERROR"
1555+
} catch (error) {x = "ERROR" }
1556+
expect(x).toBe("ERROR");
1557+
1558+
x = ""
1559+
try {
1560+
await e.evaluate(`[
1561+
[12, 42]
1562+
[33, 77]
1563+
]`);
1564+
x = "NO ERROR"
1565+
} catch (error) {x = "ERROR" }
1566+
expect(x).toBe("ERROR");
1567+
1568+
});
1569+
15091570
it('JSON parsing with a Quoted keys', async () => {
15101571
const o = await e.evaluate(`{"p1": 23, "x": [{"d" : 5}]}`);
15111572
expect(o.p1).toBe(23);

src/interpreter.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function range(start: number, stop: number = NaN, step: number = 1): number[] {
2121

2222
const INITIAL_SCOPE = {
2323
jsPython(): string {
24-
return ["JSPython v0.1.4", "(c) FalconSoft Ltd"].join('\n')
24+
return [`JSPython v0.1.8`, "(c) FalconSoft Ltd"].join('\n')
2525
},
2626
dateTime: (str: number | string | any = null) => (str && str.length)
2727
? parseDatetimeOrNull(str) || new Date() : new Date(),
@@ -32,7 +32,9 @@ const INITIAL_SCOPE = {
3232
Math: Math,
3333
Object: Object,
3434
Array: Array,
35-
JSON: JSON
35+
JSON: JSON,
36+
printExecutionContext: () => {}, // will be overriden at runtime
37+
getExecutionContext: () => {} // will be overriden at runtime
3638
};
3739

3840
interface Completion {
@@ -117,6 +119,10 @@ export class Interpreter {
117119
currentLevel: ""
118120
} as BlockContext;
119121

122+
// Two runtime methods for debugging/tracing purpose ONLY!
123+
blockContext.blockScope.printExecutionContext = () => console.log(blockContext.blockScope);
124+
blockContext.blockScope.getExecutionContext = () => blockContext.blockScope;
125+
120126
if (!instuctionLines?.length) { return null; }
121127

122128
const codeEvaluator = new EvalCodeBlock(new EvalInstruction(new EvalExpression()))

src/tokenizer.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ export class Tokenizer {
138138

139139
} while (index < text.length);
140140

141+
if(cc > 0) {
142+
throw Error(`Closing symbol '${closeBlock}' is missing.`);
143+
}
144+
141145
appendToken(chr);
142146
}
143147

0 commit comments

Comments
 (0)