/* function preload(path: Path): Object NOTE: this blocks. */ static EjsObj *workerPreload(Ejs *ejs, EjsWorker *worker, int argc, EjsObj **argv) { Ejs *inside; EjsWorker *insideWorker; EjsString *result; assert(argc > 0 && ejsIs(ejs, argv[0], Path)); assert(!worker->inside); if (worker->state > EJS_WORKER_BEGIN) { ejsThrowStateError(ejs, "Worker has already started"); return 0; } insideWorker = worker->pair; assert(insideWorker->inside); inside = insideWorker->ejs; loadFile(worker->pair, ((EjsPath*) argv[0])->value); if (inside->exception) { handleError(ejs, worker, inside->exception, 1); return 0; } result = ejsToJSON(inside, inside->result, NULL); if (result == 0) { return ESV(null); } return ejsDeserialize(ejs, result); }
/* function preeval(script: String): Object NOTE: this blocks. */ static EjsObj *workerPreeval(Ejs *ejs, EjsWorker *worker, int argc, EjsObj **argv) { Ejs *inside; EjsWorker *insideWorker; EjsString *result; assert(!worker->inside); if (worker->state > EJS_WORKER_BEGIN) { ejsThrowStateError(ejs, "Worker has already started"); return 0; } insideWorker = worker->pair; assert(insideWorker->inside); inside = insideWorker->ejs; (inside->service->loadScriptLiteral)(inside, (EjsString*) argv[0], NULL); if (inside->exception) { handleError(ejs, worker, inside->exception, 1); return 0; } result = ejsToJSON(inside, inside->result, NULL); if (result == 0) { return ESV(null); } return ejsDeserialize(ejs, result); }
/* * function preload(path: Path): String * NOTE: this blocks. */ static EjsVar *workerPreload(Ejs *ejs, EjsWorker *worker, int argc, EjsVar **argv) { Ejs *inside; EjsWorker *insideWorker; EjsVar *result; mprAssert(argc > 0 && ejsIsPath(argv[0])); mprAssert(!worker->inside); if (worker->state > EJS_WORKER_BEGIN) { ejsThrowStateError(ejs, "Worker has already started"); return 0; } insideWorker = worker->pair; inside = insideWorker->ejs; loadFile(worker->pair, ((EjsPath*) argv[0])->path); if (inside->exception) { handleError(ejs, worker, inside->exception); return 0; } result = ejsSerialize(ejs, inside->result, -1, 0, 0); if (result == 0) { return ejs->nullValue; } return ejsDeserialize(ejs, (EjsString*) result); }
/* WARNING: the inside interpreter owns the exception object. Must fully extract all fields */ static void handleError(Ejs *ejs, EjsWorker *worker, EjsObj *exception, int throwOutside) { Ejs *inside; EjsObj *e; MprDispatcher *dispatcher; Message *msg; assert(!worker->inside); assert(exception); assert(ejs == worker->ejs); ejsBlockGC(ejs); if ((msg = createMessage()) == 0) { ejsThrowMemoryError(ejs); return; } msg->worker = worker; msg->callback = "onerror"; msg->callbackSlot = ES_Worker_onerror; inside = worker->pair->ejs; inside->exception = 0; e = ejsDeserialize(ejs, ejsSerialize(inside, exception, 0)); inside->exception = exception; /* Inside interpreter owns the exception object, so must fully extract all exception. Allocate into the outside worker's interpreter. */ if (ejsIsError(inside, exception)) { msg->message = ejsGetPropertyByName(ejs, e, EN("message")); msg->stack = ejsGetPropertyByName(ejs, e, EN("stack")); } else { msg->message = e; msg->stack = 0; } if (throwOutside) { if (msg->stack) { ejsThrowStateError(ejs, "%@\n%@", ejsToString(ejs, msg->message), ejsToString(ejs, msg->stack)); } else { ejsThrowStateError(ejs, "%@", ejsToString(ejs, msg->message)); } } dispatcher = ejs->dispatcher; mprCreateEvent(dispatcher, "doMessage-error", 0, (MprEventProc) doMessage, msg, 0); }
/* Start a worker thread. This is called by eval() and load(). Not by preload() or by Worker(). It always joins. */ static EjsObj *startWorker(Ejs *ejs, EjsWorker *outsideWorker, int timeout) { EjsWorker *insideWorker; Ejs *inside; EjsString *result; assert(ejs); assert(outsideWorker); assert(!outsideWorker->inside); assert(outsideWorker->state == EJS_WORKER_BEGIN); assert(outsideWorker->pair); assert(outsideWorker->pair->ejs); mprTrace(5, "Worker.startWorker"); if (outsideWorker->state > EJS_WORKER_BEGIN) { ejsThrowStateError(ejs, "Worker has already started"); return 0; } insideWorker = outsideWorker->pair; assert(insideWorker->inside); assert(insideWorker->state == EJS_WORKER_BEGIN); inside = insideWorker->ejs; outsideWorker->state = EJS_WORKER_STARTED; if (mprCreateEvent(inside->dispatcher, "workerMain", 0, (MprEventProc) workerMain, insideWorker, 0) < 0) { ejsThrowStateError(ejs, "Cannot create worker event"); return 0; } if (timeout == 0) { return ESV(undefined); } if (timeout < 0) { timeout = MAXINT; } if (join(ejs, (EjsObj*) outsideWorker, timeout) < 0) { return ESV(undefined); } result = ejsToJSON(inside, inside->result, NULL); if (result == 0) { return ESV(null); } return ejsDeserialize(ejs, result); }
/* * Start a worker thread. This is called by eval() and load(). Not by preload() or by Worker() * It always joins. */ static EjsVar *startWorker(Ejs *ejs, EjsWorker *worker, int timeout) { Ejs *inside; EjsVar *result; mprAssert(ejs); mprAssert(worker); mprAssert(worker->state == EJS_WORKER_BEGIN); if (worker->state > EJS_WORKER_BEGIN) { ejsThrowStateError(ejs, "Worker has already started"); return 0; } mprAssert(worker->pair->state == EJS_WORKER_BEGIN); addWorker(ejs, worker); worker->state = EJS_WORKER_STARTED; worker->obj.var.permanent = 1; if (mprStartWorker(ejs, (MprWorkerProc) workerMain, (void*) worker, MPR_NORMAL_PRIORITY) < 0) { ejsThrowStateError(ejs, "Can't start worker"); worker->obj.var.permanent = 0; return 0; } if (timeout == 0) { return ejs->undefinedValue; } if (timeout < 0) { timeout = MAXINT; } if (join(ejs, (EjsVar*) worker, timeout) < 0) { ejsThrowStateError(ejs, "Timeout (%d)", timeout); return ejs->undefinedValue; } mprAssert(worker->pair); mprAssert(worker->pair->ejs); inside = worker->pair->ejs; result = ejsSerialize(ejs, inside->result, -1, 0, 0); if (result == 0) { return ejs->nullValue; } return ejsDeserialize(ejs, (EjsString*) result); }
/* function deserialize(obj: String, options: Object): Object */ PUBLIC EjsObj *g_deserialize(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv) { assert(argc >=1); return ejsDeserialize(ejs, (EjsString*) argv[0]); }