JXA: Creating object with method using Script Library

Got the same problem like described in Passing function to Script Library.

I also can create an object with properties and methods, using library. But methods become converted to empty properties.

Can anyone help please?

Can you elaborate, please? Best show your code and explain what you’re expecting to happen and what does happen.

I’ll back to my mac soon, and describe in details.

Generally, I can create an object with properties and methods, is script. Methods are working in this case.

Using library, I create the same object, but methods become empty properties — methods do not work.

Script

'use strict';

(function run() {
  let app = Application('DEVONthink 3'),
    lib = Library('demolibrary');

  app.includeStandardAdditions = true;

  let user = lib.createUser('Peter');

  app.displayAlert(user.userName); // works as needed

  app.displayAlert(user.greeting()); // displays error
})();

Library file

'use strict';

function createUser(userName) {
  let user = {
    userName: userName,
    greeting() {
      return 'Hello! My name is ' + this.userName;
    },
  };

  return user;
}

Result

BTW, if to create the object in script, everything works OK

'use strict';

(function run() {
  let app = Application('DEVONthink 3');

  app.includeStandardAdditions = true;

  let user = createUser('Peter');

  app.displayAlert(user.userName); // works as needed

  app.displayAlert(user.greeting()); // works as needed

  function createUser(userName) {
    let user = {
      userName: userName,
      greeting() {
        return 'Hello! My name is ' + this.userName;
      },
    };

    return user;
  }
})();

But this would be not DRY approach.

I see. I tried something similar and it does definitely not work as Apple says it should. What else is new …

What you could do (if you’re a really bad person, that is ;-): read the library file into a string and eval that. Yes, I know, we’re not supposed to use eval. But isn’t Apple supposed to deliver working stuff?

To read the JS file, you’ll have to use the Foundation framework. I don’t have time to whip up an example right now, but perhaps

can get you going. Otherwise, let me know.

1 Like

I suspected I have to go further and study something like ObjC.

Scripting with JXA become my starter for JXA.

Thank you, Christian, again.

Just a thumbs up (or rather down, in this case). You’re not the first person to run into this problem – see here:

So, the whole JXA library stuff is just borken. Not very helpful, I know, but at least now you know it’s not worth your while following this path. Scrap DRI.

Christian, your help made me happy!

Now, using library, I can create objects with methods — DRY!

Script

'use strict';

(function run() {
  let app = Application('DEVONthink 3'),
    lib = Library('demolibrary');

  app.includeStandardAdditions = true;

  let name = 'Peter';

  // selected record will be associated with user
  let uuid = app.selectedRecords[0].uuid();

  let code = lib.createUserCode(name, uuid);

  let user = eval(code);

  user.greeting();
})();

Library

'use strict';

function createUserCode(name, uuid) {
  let str = `
f();

function f() {
  let obj = {
    name: "${name}",
    rec: app.getRecordWithUuid('${uuid}'),
    greeting() {
      app.displayAlert(
        'Hello!\\n\\n' + 
        'My name is ' + this.name + '.' +
        '\\nMy record is "' + this.rec.name() + '".' +
        '\\n\\nYou can add methods to me!'
      );
    }
  };

  return obj;
}`;

  return str;
}

«eval is evil» — not always