crucialfelix / supercolliderjs

The JavaScript client library for SuperCollider
https://crucialfelix.github.io/supercolliderjs/
MIT License
478 stars 43 forks source link

Unhandled errors using sclang.interpret on Electron #76

Closed fibonacid closed 4 years ago

fibonacid commented 4 years ago

Cannot catch errors raised in the interpreter.

const invalidMessage = "a %%% b"

sclang.interpret(invalidMessage)
 .then(res => res)
 .catch(err => err)

The console outputs this error

[1] TypeError: Cannot read property 'errorString' of null
[1]     at Object.fn (/Users/lorenzo/Developer/Node/superorch/client/node_modules/@supercollider/lang/lib/internals/sclang-io.js:258:113)
[1]     at /Users/lorenzo/Developer/Node/superorch/client/node_modules/@supercollider/lang/lib/internals/sclang-io.js:74:29
[1]     at Array.forEach (<anonymous>)
[1]     at SclangIO.parse (/Users/lorenzo/Developer/Node/superorch/client/node_modules/@supercollider/lang/lib/internals/sclang-io.js:68:33)
[1]     at Socket.<anonymous> (/Users/lorenzo/Developer/Node/superorch/client/node_modules/@supercollider/lang/lib/sclang.js:276:35)
[1]     at Socket.emit (events.js:203:13)
[1]     at addChunk (_stream_readable.js:295:12)
[1]     at readableAddChunk (_stream_readable.js:276:11)
[1]     at Socket.Readable.push (_stream_readable.js:210:10)
[1]     at Pipe.onStreamRead (internal/stream_base_commons.js:166:17)
fibonacid commented 4 years ago

Sorry my fault, there was something wrong in my development configuration. Closing the issue

crucialfelix commented 4 years ago

I love errors that close themselves :)

fibonacid commented 4 years ago

@crucialfelix actually I was wrong, the problem is still there is this syntax still valid ?

lang.interpret(args.message).then(
      function(result) {
        // result is a native javascript array
        console.log("= " + result);
        return result;
      },
      function(error) {
        // syntax or runtime errors
        // are returned as javascript objects
        console.log('error', error);
      },
    );

The code is contained in an electron handle callback that should pass both results and errors to the renderer process. Sadly errors don't get handled. This is the code with full context.

// ... electron stuff
const sc = require("supercolliderjs");

async function bootSuperCollider() {
  const lang = await sc.lang.boot({ echo: false, debug: false });

  ipcMain.handle("interpret_sclang", async (_, args) => {
    const output = await lang.interpret(args.message).then(
      function(result) {
        // result is a native javascript array
        console.log("= " + result);
        return result;
      },
      function(error) {
        // syntax or runtime errors
        // are returned as javascript objects
        console.log('error', error);
        return error;
      },
    );

    console.log({ output });
    return output;
  });
}

bootSuperCollider();
crucialfelix commented 4 years ago

Note that you are using both await and .then:

    const output = await lang.interpret(args.message).then(

so output will be either result OR error. I guess it would work though.

You could also try writing it differently:

async (_, args) => {
  try {
    const result = await lang.interpret(args.message);
    return {result};
  } catch(error) {
    log.error(error);
    return {error};
  }
}

just to see if it reveals some other information about the problem.

fibonacid commented 4 years ago

Sadly no, the catch block is never executed and this error prompt comes up. Schermata 2020-01-30 alle 15 13 46

crucialfelix commented 4 years ago

The error object should be SCLangError which is a subclass of Error

https://crucialfelix.github.io/supercolliderjs/#/packages/lang/SCLang?id=interpret

https://crucialfelix.github.io/supercolliderjs/#/packages/supercolliderjs/SCLangError

I can see from your stack trace that you are using the previous release (before the typescript port)

but the code is the same:

                obj = JSON.parse(stdout);
// ...
                      new SCLangError(`Interpret error: ${obj["errorString"]}`, response.type, err || obj),

So if stdout was empty then it isn't an object. I should check that it did result in an object.

Could you post what the .message (code input) is?

fibonacid commented 4 years ago

The input was ciao without quotation marks and pointing to nothing. The version I'm using it's "1.0.0"

crucialfelix commented 4 years ago
const sc = require("supercolliderjs");

sc.lang.boot().then(async function(lang) {
  const ciao = await lang.interpret("ciao");
  console.log(ciao);

  await lang.quit();
});
/Users/crucialfelix/code/supercolliderjs/packages/lang/lib/internals/sclang-io.js:258
                                        this.calls[guid].reject(new Errors_1.SCLangError(`Interpret error: ${obj["errorString"]}`, response.type, err || obj));
                                                                                                                ^

TypeError: Cannot read property 'errorString' of null
    at Object.fn (/Users/crucialfelix/code/supercolliderjs/packages/lang/lib/internals/sclang-io.js:258:113)
    at states.(anonymous function).forEach (/Users/crucialfelix/code/supercolliderjs/packages/lang/lib/internals/sclang-io.js:74:29)
    at Array.forEach (<anonymous>)
    at SclangIO.parse (/Users/crucialfelix/code/supercolliderjs/packages/lang/lib/internals/sclang-io.js:68:33)
    at Socket.subprocess.stdout.on.data (/Users/crucialfelix/code/supercolliderjs/packages/lang/lib/sclang.js:276:35)
    at Socket.emit (events.js:189:13)
    at addChunk (_stream_readable.js:284:12)
    at readableAddChunk (_stream_readable.js:265:11)
    at Socket.Readable.push (_stream_readable.js:220:10)
    at Pipe.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
examples ❯                                                                                                                                                         ⏎

bug confirmed!

crucialfelix commented 4 years ago
const sc = require("supercolliderjs");

sc.lang.boot().then(async function(lang) {
  try {
    const ciao = await lang.interpret("ciao");
    console.log(ciao);
  } catch (error) {
    console.error(error);
  }

  await lang.quit();
});
examples ❯ node "/Users/crucialfelix/code/supercolliderjs/examples/lang-error.js"
(node:93586) ExperimentalWarning: The fs.promises API is experimental
SCLangError {
  data: {},
  type: 'SyntaxError',
  error:
   { msg: 'Variable \'ciao\' not defined.',
     file: null,
     line: 1,
     charPos: 4,
     code: 'ciao' } }

fix coming...

crucialfelix commented 4 years ago

1.0.1 is released.

fibonacid commented 4 years ago

Thank you!

is it on npm already ?