Server-Side JavaScript support
With MarkLogic 8, it would great to be able to specify tasks as JavaScript in addition to XQuery. I don't know how much surgery this would be; I haven't tested it. Worst case is a parallel rewrite, though I think the orchestration could remain in XQuery and the user-specified task and filter logic could be pluggable with JavaScript. I’ll take a first crack at characterizing the changes and propose something in a pull request.
To make this happen I think we need to solve two problems. They seem to be closely related, so solving either will probably solve both.
First, we need xdmp:invoke-function and xdmp:spawn-function to accept JavaScript functions instead of throwing XDMP-AS: (err:XPTY0004) xdmp:invoke-function($fn) -- Invalid coercion: function () as function() as item()*.
Related to that, we need function type specifiers to work with JavaScript while remaining backward-compatible with ML7. In various places taskbot's functions expect $fn as function() as item()* and $fn as function(item()+, map:map?) as item()* and $fn as function() as xs:boolean. Today those all reject JavaScript functions. Here's a simple test case to give you the idea:
declare function local:test($fn as function() as item()*)
{
$fn()
};
local:test(function() { current-dateTime() }),
local:test(xdmp:javascript-eval('var f = function() { return new Date(); }; f;'))
XDMP-AS: (err:XPTY0004) $fn as function() as item()* -- Invalid coercion: function () as function() as item()*
The difference appears to be cosmetic: if I change the signature to $fn as item() or drop the typing entirely, then both tests work. I recognize that I might have to weaken some of those function types to account for the nature of JavaScript. But despite that I want to retain as much strong typing as possible inside the taskbot code. Anyway the fixes for xdmp:invoke-function and xdmp:spawn-function should solve at least part of this.
Unfortunately a JavaScript equivalent of xdmp:spawn-function will not be available in 8.0-1. It’s something we definitely want to do, but there are some issues with V8 isolation boundaries that make this infeasible in the short term. That sounds like a blocker here.
Yes, that looks like a show-stopper. Calling xdmp:spawn-function throws the same XDMP-AS above. I thought it might be possible to encapsulate the JavaScript function in an anonymous XQuery function, but that also fails.
let $fn := xdmp:javascript-eval(
'var f = function() { xdmp.log("hello from javascript!"); }; f;')
return xdmp:spawn-function(
function() {
xdmp:log('test start'),
$fn() })
That logs an error:
2014-12-10 12:57:57.635 Info: TaskServer: test start
2014-12-10 12:57:57.636 Notice: TaskServer: JS-APPLY: function() as item()*() -- Cannot apply function:
2014-12-10 12:57:57.636 Notice: TaskServer: in / [1.0-ml]
A similar test with xdmp:invoke-function works, so this looks like a V8 problem.