FontoXML / fontoxpath

A minimalistic XPath 3.1 implementation in pure JavaScript
MIT License
135 stars 17 forks source link

Exceptions no longer stringify #628

Closed rrthomas closed 9 months ago

rrthomas commented 10 months ago

In past versions of fontoxpath, exceptions would stringify to the error message. This seems no longer to be the case; they just give the dreaded [object Object].

I can recover the error message by printing error.h (in version 3.30.2), but that's fragile and depends on the minification of the exception object.

rrthomas commented 10 months ago

Further, if running with DEBUG=yes, the error message in traceback just becomes the rather obscure #<Mh> :)

bwrrp commented 9 months ago

Hi, I'm unfortunately not able to reproduce this using the following code (in a new node.js project with fontoxpath 3.30.2):

const f = require('fontoxpath');
let e = null;
try {
    f.evaluateXPathToBoolean('fn:error("test")', null);
} catch (err) {
    e = err;
}

console.log({
    stringified: e.toString(),
    message: e.message,
    instanceOfError: e instanceof Error
});

Results in:

{
  stringified: 'Error: XPTY0004 Unable to cast argument of type xs:string to type xs:QName? while calling error',
  message: 'XPTY0004 Unable to cast argument of type xs:string to type xs:QName? while calling error',
  instanceOfError: true
}

Perhaps you have a minifier on your end that's causing trouble here?

rrthomas commented 9 months ago

I'm not using a minifier as far as I know (plain TypeScript compilation in a Node project). I've not changed anything in my build system since it last worked. I can find the "Mh" symbol in the distributed fontoxpath dist/fontoxpath.esm.js, which is minified.

bwrrp commented 9 months ago

Hmm, that seems to correspond to the internal StackTraceEntry class, which is supposed to remain internal as it should be caught and converted to a proper error. It seems we might have missed a spot there. Are you able to provide more details on the specific API / XPath being used here (or maybe even a stack trace?) to help track down where we missed a catch?

rrthomas commented 9 months ago

Sure! Will see what I can do. I have confirmed that if I run identical code with 3.30.2 and 3.28.2 then the serialization works with 3.28.2 but not 3.30.2. I'll see if I can get a backtrace now.

rrthomas commented 9 months ago

With 3.30.2:

(node:860382) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("ts-node/esm", pathToFileURL("./"));'
(Use `node --trace-warnings ...` to show where the warning was created)

node:internal/process/esm_loader:40
      internalBinding('errors').triggerUncaughtException(
                                ^
Mh {
  location: {
    start: { offset: 113, line: 5, ha: 1 },
    end: { offset: 114, line: 5, ha: 2 }
  },
  o: '',
  Wa: '',
  h: Error: XPST0003: Failed to parse script. Expected ;
      at jq (/home/rrt/Software/ruth/node_modules/fontoxpath/dist/fontoxpath.js:403:726)
      at Wu (/home/rrt/Software/ruth/node_modules/fontoxpath/dist/fontoxpath.js:567:206)
      at loadModule (file:///home/rrt/Software/ruth/src/index.ts:40:5)
      at objToNode (file:///home/rrt/Software/ruth/src/index.ts:194:25)
      at file:///home/rrt/Software/ruth/src/index.ts:165:60
      at Array.forEach (<anonymous>)
      at objToNode (file:///home/rrt/Software/ruth/src/index.ts:165:23)
      at Expander.dirTreeToXml (file:///home/rrt/Software/ruth/src/index.ts:209:26)
      at new XmlDir (file:///home/rrt/Software/ruth/src/index.ts:98:27)
      at new Expander (file:///home/rrt/Software/ruth/src/index.ts:233:8)
      at file:///home/rrt/Software/ruth/src/cli.ts:36:5
      at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
      at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
      at async loadESM (node:internal/process/esm_loader:34:7)
      at async handleMainPromise (node:internal/modules/run_main:113:12)
}

With 3.28.2:

(node:865019) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("ts-node/esm", pathToFileURL("./"));'
(Use `node --trace-warnings ...` to show where the warning was created)
/home/rrt/Software/ruth/node_modules/fontoxpath/dist/fontoxpath.js:474
[n]:[]),[r])}),wu=T.complete(U(vu,W));return function(n,r){m.clear();r=wu(n,r);for(var E=1,ea=1,oa=0;oa<n.length+1;oa++){if(m.has(oa)){var Ka=m.get(oa);Ka.line=ea;Ka.ma=E}Ka=n[oa];"\r"===Ka||"\n"===Ka?(ea++,E=1):E++}return r}}var Iq=Hq({ub:!1,Xa:!1}),Jq=Hq({ub:!0,Xa:!1}),Kq=Hq({ub:!1,Xa:!0}),Lq=Hq({ub:!0,Xa:!0});function Mq(a,b){var c=!!b.aa;b=!!b.debug;mp.clear();np.clear();Gq.clear();c=c?b?Lq(a,0):Kq(a,0):b?Jq(a,0):Iq(a,0);if(!0===c.success)return c.value;throw Error("XPST0003: Failed to parse '"+a+"' expected: "+c.expected+"\n"+(a.slice(0,c.offset)+"[Error is around here]"+a.slice(c.offset)));};var Nq="http://www.w3.org/XML/1998/namespace http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2005/xpath-functions http://www.w3.org/2005/xpath-functions/math http://www.w3.org/2012/xquery http://www.w3.org/2005/xpath-functions/array http://www.w3.org/2005/xpath-functions/map".split(" ");
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ^

Error: XPST0003: Failed to parse '(: Some syntactically-invalid XQuery: missing semicolon at end of function :)
declare function foo() {
  "bar"
}
' expected: end of input
(: Some syntactically-invalid XQuery: missing semicolon at end of function :)
declare [Error is around here]function foo() {
  "bar"
}

    at Mq (/home/rrt/Software/ruth/node_modules/fontoxpath/dist/fontoxpath.js:474:469)
    at yv (/home/rrt/Software/ruth/node_modules/fontoxpath/dist/fontoxpath.js:600:237)
    at loadModule (file:///home/rrt/Software/ruth/src/index.ts:40:5)
    at objToNode (file:///home/rrt/Software/ruth/src/index.ts:194:25)
    at file:///home/rrt/Software/ruth/src/index.ts:165:60
    at Array.forEach (<anonymous>)
    at objToNode (file:///home/rrt/Software/ruth/src/index.ts:165:23)
    at Expander.dirTreeToXml (file:///home/rrt/Software/ruth/src/index.ts:209:26)
    at new XmlDir (file:///home/rrt/Software/ruth/src/index.ts:98:27)
    at new Expander (file:///home/rrt/Software/ruth/src/index.ts:233:8)
    at file:///home/rrt/Software/ruth/src/cli.ts:36:5
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:34:7)
    at async handleMainPromise (node:internal/modules/run_main:113:12)
bwrrp commented 9 months ago

Aha, thanks for that! It looks like registerXQueryModule is missing a catch-and-rethrow around its attempt to parse the input.