FontoXML / fontoxpath

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

Exceptions no longer stringify #628

Closed rrthomas closed 7 months ago

rrthomas commented 7 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 7 months ago

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

bwrrp commented 7 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 7 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 7 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 7 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 7 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 7 months ago

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