Bug: JXA .whose() query fails with values of row.state()

There is an ambiguity in the type of OO checkboxes (row state checkboxes have a different type from user column checkboxes) which may be the source of a bug in the JavaScript for Applications interface to OO.

This well-formed code trips an error:

Application("OmniOutliner").documents.at(0).rows.whose({"state": "unchecked"}).length
Error -1700: Can't convert types.

though the same form works with all other row properties, and this desugared version, which refers to the same property and value, and is in principle identical, succeeds:

Application("OmniOutliner").documents.at(0).rows.whose({_match: [ObjectSpecifier().state, "unchecked"]}).length

A clue to what is failing may be that while the possible values of checkboxes:

  • ‘checked’,
  • ‘unchecked’
  • ‘indeterminate’

are shown in the JS .sdef as strings, both in the the case of row state boxes,

and user column checkboxes:

In the AS interface the values of state boxes and cell boxes have different types (enumeration integers in state boxes

vs actual strings in user cells)

I ran this by the developer who designed our scripting implementation in OmniOutliner. Here are his notes:

Not sure I’m exactly getting the jist of the question, but a couple notes…

  • value can’t return a state enum (as I recall) since those are four-character codes. We currently have the return type on those methods as FourCharCode. We might be able to use NSNumber, but this would cause confusion in number columns since in both cases we need to return a number object and the system can’t tell if you mean the enum or an actual number. I don’t recall if there were other issues the last time I looked at this (originally I wanted to just have value and do the type based on the column).
  • Cells in checkbox columns can be accessed with state too and will return the enum.
  • On the -1700 case, though, it sounds like JXA is smashing strings through w/o converting them to the enum in whose clauses? This seems like a JXA bug… we get an AppleEvent with a string in it instead:

aevt(‘core’‘cnte’ transactionID=0 sourcePSN=[0x0,13b13b “Script Editor”] eventSource=3 sourceUID=502 sourceGID=20 sourceEUID=502 sourceEGID=20 sourcePID=619 auditToken=[502,502,20,502,20,619,100008,100337]{ ‘kocl’:type(‘cobj’), ‘----’:obj ('obj ‘{ ‘want’:type(‘OOrw’), ‘form’:enum(‘test’), ‘seld’:cmpd(‘cmpd’{ ‘relo’:enum(’= '), ‘obj1’:obj ('obj '{ ‘form’:enum(‘prop’), ‘want’:type(‘prop’), ‘seld’:type(‘OOst’), ‘from’:exmn(‘exmn’($$)) }), ‘obj2’:utxt(‘utxt’(TEXT(“unchecked”))) }), ‘from’:obj ('obj '{ ‘want’:type(‘docu’), ‘form’:enum(‘indx’), ‘seld’:long(1), ‘from’:null() }) }) })

instead of the AppleEvent we get when the equivalent AppleScript is run:

aevt(‘core’‘getd’ transactionID=0 sourcePSN=[0x0,13b13b “Script Editor”] eventSource=3 sourceUID=502 sourceGID=20 sourceEUID=502 sourceEGID=20 sourcePID=619 auditToken=[502,502,20,502,20,619,100008,100337]{ ‘----’:obj ('obj '{ ‘form’:enum(‘test’), ‘want’:type(‘OOrw’), ‘from’:obj ('obj ‘{ ‘form’:enum(‘indx’), ‘want’:type(‘docu’), ‘seld’:long(1), ‘from’:null() }), ‘seld’:cmpd(‘cmpd’{ ‘relo’:enum(’= '), ‘obj1’:obj ('obj '{ ‘form’:enum(‘prop’), ‘want’:type(‘prop’), ‘seld’:type(‘OOst’), ‘from’:exmn(‘exmn’($$)) }), ‘obj2’:enum(‘OOS0’) }) }), &‘cons’:list([ enum(‘case’) ]), &‘csig’:magn(65536) })

In the text case, the error originates when -coerceToDescriptorType: is called with typeAERecord on the offending text and it returns -[NSScriptEnumerationDescription errorExpectedTypeDescriptor] — so this all happens down at the descriptor level before any of our code is invoked at all.

So… as far as I can see, we can’t change our sdef for value and they can’t use state on row. It seems like JXA needs to do proper type mapping for ‘whose’ specifier elements …

I’m not sure how actively Apple is fixing issues with JXA, but in an ideal world it seems like that would be the best place to fix this problem.

1 Like

That makes a lot of sense.

Many thanks to all for taking the time to look into it – much appreciated.