You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
One of VBScript's most embarrassing parts is its error handling. Basically you can turn it on and off at any time, at runtime. Error handling by side-effect, yay.
In JavaScript, there is no such thing. You can define a global error handler, but that won't resume code execution. For VBScript's API, that's less of a problem because we can handle errors ourselves (i.e. set the Err object accordingly), but for language features this doesn't work.
The first time we encounter this problem is how core.vbs updates lamps:
If the ROM returns a lamp index that doesn't exist on the playfield, our transpiled script currently crashes, because Lights[idx] returns undefined, and undefined.State throws an error.
In VBScript this works, because error handling muted by On Error Resume Next. If Lights(idx) doesn't exist, well, never mind and continue.
There are a few ways of handling that, none particularly elegant.
Wrap every statement into a function
Since whether throw or swallow errors is a runtime condition, we can't determine at compile time which statements to wrap into a function that doesn't throw in case errors are muted. That means wrapping every statement of the table script into a function.
Apart from the code becoming an unreadable mess, this is also pretty bad for performance. Take the following snippet:
Click to view
functionwrap(fct){try{fct();}catch{// no nothing}}constni=1e9;consto={};consttime1=Date.now();for(leti=0;i<ni;i++){o.test=i;}constdTime1=Date.now()-time1;consttime2=Date.now();for(leti=0;i<ni;i++){wrap(()=>o.test=i);}constdTime2=Date.now()-time2;console.log('before: %sms',dTime1);console.log('after: %sms',dTime2);
Results with one billion iterations:
before
after
Node.js 12.8, Win64
551ms
3064ms
Chrome 78, Win64
545ms
2349ms
Chrome Canary 80
602ms
3621ms
So this adds factor three to six. Which is pretty bad. Maybe there are sufficiently little statements in an average table script to stays below budget, but I doubt that.
Wrap only language features
We could start by wrapping only member assignments, until the next road block. At some point we might need to be able to catch division by zero as well and end up like the first solutions, but it would be a more lightweight approach.
Concretely, Lights(idx).State = ChgLamp(ii, 1) would compile to __vbsHelper.set(Lights[idx], 'State', ChgLamp[ii][1]), and the set method would only fail if error handling is enabled.
Fix this specific case by returning fake-lights
Our table could simply return 200 lights like core.vbs loops over that do nothing, and this particular case would be solved. It comes with a (memory) overhead as well, and doesn't solve the actual problem.
Use a core.vbs that doesn't rely on On Error
We can also fix this at the source, at core.vbs. We've got our hands on it, since we bundle it. This would however mean that as core.vbs evolves in the future, we need to re-apply our patches (does happen a few times a year). It also doesn't solve the problem for in-table shipped scripts.
Conclusion
I would reevaluate this once we get core.vbs working. If there are no other cases, we might as well use the third approach. If there are more, but only for undefined properties, the second approach might be better. The first one, while the "most proper" one, should be avoided, given the performance hit.
The text was updated successfully, but these errors were encountered:
One of VBScript's most embarrassing parts is its error handling. Basically you can turn it on and off at any time, at runtime. Error handling by side-effect, yay.
In JavaScript, there is no such thing. You can define a global error handler, but that won't resume code execution. For VBScript's API, that's less of a problem because we can handle errors ourselves (i.e. set the
Err
object accordingly), but for language features this doesn't work.The first time we encounter this problem is how
core.vbs
updates lamps:If the ROM returns a lamp index that doesn't exist on the playfield, our transpiled script currently crashes, because
Lights[idx]
returnsundefined
, andundefined.State
throws an error.In VBScript this works, because error handling muted by
On Error Resume Next
. IfLights(idx)
doesn't exist, well, never mind and continue.There are a few ways of handling that, none particularly elegant.
Wrap every statement into a function
Since whether throw or swallow errors is a runtime condition, we can't determine at compile time which statements to wrap into a function that doesn't throw in case errors are muted. That means wrapping every statement of the table script into a function.
Apart from the code becoming an unreadable mess, this is also pretty bad for performance. Take the following snippet:
Click to view
So this adds factor three to six. Which is pretty bad. Maybe there are sufficiently little statements in an average table script to stays below budget, but I doubt that.
Wrap only language features
We could start by wrapping only member assignments, until the next road block. At some point we might need to be able to catch division by zero as well and end up like the first solutions, but it would be a more lightweight approach.
Concretely,
Lights(idx).State = ChgLamp(ii, 1)
would compile to__vbsHelper.set(Lights[idx], 'State', ChgLamp[ii][1])
, and theset
method would only fail if error handling is enabled.Fix this specific case by returning fake-lights
Our table could simply return 200 lights like
core.vbs
loops over that do nothing, and this particular case would be solved. It comes with a (memory) overhead as well, and doesn't solve the actual problem.Use a
core.vbs
that doesn't rely onOn Error
We can also fix this at the source, at
core.vbs
. We've got our hands on it, since we bundle it. This would however mean that ascore.vbs
evolves in the future, we need to re-apply our patches (does happen a few times a year). It also doesn't solve the problem for in-table shipped scripts.Conclusion
I would reevaluate this once we get
core.vbs
working. If there are no other cases, we might as well use the third approach. If there are more, but only for undefined properties, the second approach might be better. The first one, while the "most proper" one, should be avoided, given the performance hit.The text was updated successfully, but these errors were encountered: