PUBLIC EjsFile *ejsCreateFileFromFd(Ejs *ejs, int fd, cchar *name, int mode) { EjsFile *fp; assert(fd >= 0); assert(name); if ((fp = ejsCreateObj(ejs, ESV(File), 0)) == NULL) { return NULL; } fp->perms = EJS_FILE_PERMS; fp->mode = EJS_FILE_OPEN; if (!(mode & O_WRONLY)) { fp->mode |= EJS_FILE_READ; } if (mode & (O_WRONLY | O_RDWR)) { fp->mode |= EJS_FILE_WRITE; } if ((fp->file = mprAttachFileFd(fd, name, mode)) == 0) { return 0; } fp->attached = 1; fp->path = MPR->emptyString; return fp; }
/* Create an initialized regular expression object. The pattern should include the slash delimiters. For example: /abc/ or /abc/g */ EjsRegExp *ejsCreateRegExp(Ejs *ejs, EjsString *pattern) { EjsRegExp *rp; cchar *errMsg; MprChar *flags; int column, errCode; if (pattern->length == 0 || pattern->value[0] != '/') { ejsThrowArgError(ejs, "Bad regular expression pattern. Must start with '/'"); return 0; } rp = ejsCreateObj(ejs, ESV(RegExp), 0); if (rp != 0) { /* Strip off flags for passing to pcre_compile2 */ rp->pattern = sclone(&pattern->value[1]); if ((flags = wrchr(rp->pattern, '/')) != 0) { rp->options = parseFlags(rp, &flags[1]); *flags = 0; } // TODO - UNICODE is pattern meant to be rp->compiled = pcre_compile2(rp->pattern, rp->options, &errCode, &errMsg, &column, NULL); if (rp->compiled == NULL) { ejsThrowArgError(ejs, "Can't compile regular expression '%s'. Error %s at column %d", rp->pattern, errMsg, column); return 0; } } return rp; }
PUBLIC EjsUri *ejsCreateUri(Ejs *ejs, EjsString *path) { EjsUri *up; if ((up = ejsCreateObj(ejs, ESV(Uri), 0)) == NULL) { return 0; } uri_constructor(ejs, up, 1, (EjsObj**) &path); return up; }
/* function relative(base): Uri */ static EjsUri *uri_relative(Ejs *ejs, EjsUri *up, int argc, EjsObj **argv) { EjsUri *result; HttpUri *baseUri; baseUri = toHttpUri(ejs, argv[0], 0); result = ejsCreateObj(ejs, ESV(Uri), 0); result->uri = httpGetRelativeUri(baseUri, up->uri, 1); return result; }
static EjsUri *cloneUri(Ejs *ejs, EjsUri *src, bool deep) { EjsUri *dest; if ((dest = ejsCreateObj(ejs, TYPE(src), 0)) == 0) { return 0; } /* NOTE: a deep copy will complete the uri */ dest->uri = httpCloneUri(src->uri, deep ? HTTP_COMPLETE_URI : 0); return dest; }
PUBLIC EjsUri *ejsCreateUriFromParts(Ejs *ejs, cchar *scheme, cchar *host, int port, cchar *path, cchar *query, cchar *reference, int flags) { EjsUri *up; if ((up = ejsCreateObj(ejs, ESV(Uri), 0)) == 0) { return 0; } up->uri = httpCreateUriFromParts(scheme, host, port, path, reference, query, flags); return up; }
PUBLIC EjsUri *ejsCreateUriFromAsc(Ejs *ejs, cchar *path) { EjsUri *up; EjsObj *arg; if ((up = ejsCreateObj(ejs, ESV(Uri), 0)) == 0) { return 0; } arg = (EjsObj*) ejsCreateStringFromAsc(ejs, path); uri_constructor(ejs, up, 1, (EjsObj**) &arg); return up; }
static EjsObj *cloneXmlList(Ejs *ejs, EjsXML *list, bool deep) { EjsXML *newList; // TODO - implement deep copy newList = ejsCreateObj(ejs, TYPE(list), 0); if (newList == 0) { ejsThrowMemoryError(ejs); return 0; } // TODO incomplete return (EjsObj*) newList; }
PUBLIC void ejsCreateVoidType(Ejs *ejs) { EjsType *type; type = ejsCreateCoreType(ejs, N("ejs", "Void"), sizeof(EjsVoid), S_Void, ES_Void_NUM_CLASS_PROP, NULL, EJS_TYPE_OBJ); type->helpers.cast = (EjsCastHelper) castVoid; type->helpers.invokeOperator = (EjsInvokeOperatorHelper) invokeVoidOperator; type->helpers.getProperty = (EjsGetPropertyHelper) getVoidProperty; ejsAddImmutable(ejs, ES_undefined, EN("undefined"), ejsCreateObj(ejs, type, 0)); mprSetName(ESV(undefined), "undefined"); }
/* Parse a regular expression string. The string should include the slash delimiters and may contain appended flags. For example: /abc/ or /abc/g */ PUBLIC EjsRegExp *ejsParseRegExp(Ejs *ejs, EjsString *pattern) { EjsRegExp *rp; cchar *errMsg; char *cp, *dp; wchar *flags; int column, errCode; if (pattern->length == 0 || pattern->value[0] != '/') { ejsThrowArgError(ejs, "Bad regular expression pattern. Must start with '/'"); return 0; } if ((rp = ejsCreateObj(ejs, ESV(RegExp), 0)) == 0) { return 0; } /* Strip off flags for passing to pcre_compile2 */ if (pattern->value[0] == '/') { rp->pattern = sclone(&pattern->value[1]); if ((flags = wrchr(rp->pattern, '/')) != 0) { if (flags == rp->pattern) { ejsThrowArgError(ejs, "Bad regular expression pattern. Must end with '/'"); return 0; } rp->options = parseFlags(rp, &flags[1]); *flags = 0; } /* NOTE: we don't expect backquotes to be quoted. That only happens when interpreting literal js code and JSON */ for (dp = cp = rp->pattern; *cp; ) { if (*cp == '\\' && cp[1] == '/') { cp++; } *dp++ = *cp++; } *dp++ = '\0'; } else { rp->pattern = sclone(&pattern->value[1]); } rp->compiled = pcre_compile2(rp->pattern, rp->options, &errCode, &errMsg, &column, NULL); if (rp->compiled == NULL) { ejsThrowArgError(ejs, "Cannot compile regular expression '%s'. Error %s at column %d", rp->pattern, errMsg, column); return 0; } return rp; }
/* Create an iterator. */ EjsIterator *ejsCreateIterator(Ejs *ejs, EjsAny *obj, int length, void *nativeNext, bool deep, EjsArray *namespaces) { EjsIterator *ip; if ((ip = ejsCreateObj(ejs, ESV(Iterator), 0)) != 0) { ip->index = 0; ip->indexVar = 0; ip->nativeNext = nativeNext; ip->target = obj; ip->length = length; ip->deep = deep; ip->namespaces = namespaces; } return ip; }
PUBLIC EjsFile *ejsCreateFile(Ejs *ejs, cchar *path) { EjsFile *fp; EjsObj *arg; assert(path && *path); fp = ejsCreateObj(ejs, ESV(File), 0); if (fp == 0) { return 0; } arg = (EjsObj*) ejsCreateStringFromAsc(ejs, path); fileConstructor(ejs, fp, 1, (EjsObj**) &arg); return fp; }
/* function resolve(target): Uri */ static EjsUri *uri_resolve(Ejs *ejs, EjsUri *up, int argc, EjsObj **argv) { EjsUri *result; HttpUri *uri, *target; uri = up->uri; target = toHttpUri(ejs, argv[0], 0); result = ejsCreateObj(ejs, ESV(Uri), 0); uri = httpResolveUri(uri, 1, &target, 0); if (up->uri == uri) { uri = httpCloneUri(uri, 0); } result->uri = uri; return result; }
/* Copy all properties of the instance including all references. If deep is true and if some properties are reference types, then recursively copy all their properties and so on. @param ejs VM handle. @param sp is set to the object instance to clone. @return The newly copied object */ static EjsObj *cloneShape(Ejs *ejs, Shape *sp, bool deep) { Shape *newShape; newShape = ejsCreateObj(ejs, TYPE(sp), 0); if (newShape == 0) { ejsThrowMemoryError(ejs); return 0; } newShape->x = sp->x; newShape->y = sp->y; newShape->height = sp->height; newShape->width = sp->width; return (EjsObj*) newShape; }
/* Create an initialized regular expression object. The pattern should NOT include the slash delimiters. */ PUBLIC EjsRegExp *ejsCreateRegExp(Ejs *ejs, cchar *pattern, cchar *flags) { EjsRegExp *rp; cchar *errMsg; int column, errCode; if ((rp = ejsCreateObj(ejs, ESV(RegExp), 0)) == 0) { return 0; } rp->pattern = sclone(pattern); rp->options = parseFlags(rp, (wchar*) flags); rp->compiled = pcre_compile2(rp->pattern, rp->options, &errCode, &errMsg, &column, NULL); if (rp->compiled == NULL) { ejsThrowArgError(ejs, "Cannot compile regular expression '%s'. Error %s at column %d", rp->pattern, errMsg, column); return 0; } return rp; }
static EjsUri *completeUri(Ejs *ejs, EjsUri *up, EjsObj *missing, int includeQuery) { EjsUri *missingUri; if (!ejsIsDefined(ejs, missing)) { missingUri = 0; } else if (ejsGetLength(ejs, missing) > 0) { missingUri = ejsCreateObj(ejs, ESV(Uri), 0); missingUri->uri = createHttpUriFromHash(ejs, missing, HTTP_COMPLETE_URI); } else { missingUri = ejsToUri(ejs, missing); } if (missingUri == 0) { if (!includeQuery) { up->uri->query = NULL; } httpCompleteUri(up->uri, NULL); } else { httpCompleteUri(up->uri, missingUri->uri); } return up; }
/* Convert an arg to a URI. Can handle strings, paths, URIs and object hashes. Will cast all else to strings and then parse. */ static EjsUri *castToUri(Ejs *ejs, EjsObj *arg) { EjsUri *up; up = ejsCreateObj(ejs, ESV(Uri), 0); if (ejsIs(ejs, arg, String)) { up->uri = httpCreateUri(up, ejsToMulti(ejs, arg), 0); } else if (ejsIs(ejs, arg, Uri)) { up->uri = httpCloneUri(((EjsUri*) arg)->uri, 0); } else if (ejsIs(ejs, arg, Path)) { ustr = ((EjsPath*) arg)->path; up->uri = httpCreateUri(up, ustr, 0); } else if (ejsGetLength(ejs, arg) > 0) { up->uri = createHttpUriFromHash(ejs, up, arg, 0); } else { arg = (EjsObj) ejsToString(ejs, arg); up->uri = httpCreateUri(up, ejsToMulti(ejs, arg), 0); } return up; }
/* return a default mpr object */ struct MprVar mprObject(const char *name) { return ejsCreateObj(name && *name?name:"(NULL)", MPR_DEFAULT_HASH_SIZE); }
static void onWebSocketEvent(EjsWebSocket *ws, int event, EjsAny *data, HttpPacket *packet) { Ejs *ejs; EjsAny *eobj; EjsFunction *fn; HttpRx *rx; cchar *eventName, *reason; int slot, status; ejs = ws->ejs; rx = ws->conn->rx; eobj = ejsCreateObj(ejs, ESV(Object), 0); slot = -1; eventName = 0; switch(event) { case HTTP_EVENT_READABLE: slot = ES_WebSocket_onmessage; eventName = "readable"; assert(data); ejsSetPropertyByName(ejs, eobj, EN("data"), data); ejsSetPropertyByName(ejs, eobj, EN("last"), ejsCreateBoolean(ejs, packet->last)); ejsSetPropertyByName(ejs, eobj, EN("type"), ejsCreateNumber(ejs, packet->type)); break; case HTTP_EVENT_ERROR: eventName = "error"; slot = ES_WebSocket_onerror; break; case HTTP_EVENT_APP_OPEN: slot = ES_WebSocket_onopen; eventName = "headers"; if (rx->webSocket) { httpSetWebSocketPreserveFrames(ws->conn, ws->frames); } break; case HTTP_EVENT_DESTROY: if (ws->closed) { break; } ws->closed = 1; /* Fall through to close */ case HTTP_EVENT_APP_CLOSE: eventName = "complete"; slot = ES_WebSocket_onclose; status = rx ? rx->webSocket->closeStatus: WS_STATUS_COMMS_ERROR; reason = rx ? rx->webSocket->closeReason: 0; ejsSetPropertyByName(ejs, eobj, EN("code"), ejsCreateNumber(ejs, status)); ejsSetPropertyByName(ejs, eobj, EN("reason"), ejsCreateStringFromAsc(ejs, reason)); ejsSetPropertyByName(ejs, eobj, EN("wasClean"), ejsCreateBoolean(ejs, status != WS_STATUS_COMMS_ERROR)); break; } if (slot >= 0) { if (ws->emitter) { ejsSendEvent(ejs, ws->emitter, eventName, ws, data); } fn = ejsGetProperty(ejs, ws, slot); if (ejsIsFunction(ejs, fn) && !ejs->exception) { ejsRunFunction(ejs, fn, ws, 1, &eobj); } } }
PUBLIC EjsWorker *ejsCreateWorker(Ejs *ejs) { return ejsCreateObj(ejs, ESV(Worker), 0); }
/* Process a message sent from postMessage. This may run inside the worker or outside in the parent depending on the direction of the message. But it ALWAYS runs in the appropriate thread for the interpreter. */ static int doMessage(Message *msg, MprEvent *mprEvent) { Ejs *ejs; EjsObj *event, *frame; EjsWorker *worker; EjsFunction *callback; EjsObj *argv[1]; worker = msg->worker; worker->gotMessage = 1; ejs = worker->ejs; assert(!ejs->exception); event = 0; ejsBlockGC(ejs); callback = ejsGetProperty(ejs, worker, msg->callbackSlot); switch (msg->callbackSlot) { case ES_Worker_onerror: event = ejsCreateObj(ejs, ESV(ErrorEvent), 0); break; case ES_Worker_onclose: case ES_Worker_onmessage: event = ejsCreateObj(ejs, ESV(Event), 0); break; default: assert(msg->callbackSlot == 0); return 0; } worker->event = event; if (msg->data) { ejsSetProperty(ejs, event, ES_Event_data, ejsCreateStringFromAsc(ejs, msg->data)); } if (msg->message) { ejsSetProperty(ejs, event, ES_ErrorEvent_message, msg->message); } if (msg->stack) { ejsSetProperty(ejs, event, ES_ErrorEvent_stack, msg->stack); if ((frame = ejsGetProperty(ejs, msg->stack, 0)) != 0 && !ejsIs(ejs, frame, Void)) { ejsSetProperty(ejs, event, ES_ErrorEvent_filename, ejsGetPropertyByName(ejs, frame, EN("filename"))); ejsSetProperty(ejs, event, ES_ErrorEvent_lineno, ejsGetPropertyByName(ejs, frame, EN("lineno"))); } } assert(!ejs->exception); if (callback == 0 || ejsIs(ejs, callback, Null)) { if (msg->callbackSlot == ES_Worker_onmessage) { mprTrace(6, "Discard message as no onmessage handler defined for worker"); } else if (msg->callbackSlot == ES_Worker_onerror) { if (ejsIs(ejs, msg->message, String)) { ejsThrowError(ejs, "Exception in Worker: %@", ejsToString(ejs, msg->message)); } else { ejsThrowError(ejs, "Exception in Worker: %s", ejsGetErrorMsg(worker->pair->ejs, 1)); } } else { /* Ignore onclose message */ } } else if (!ejsIsFunction(ejs, callback)) { ejsThrowTypeError(ejs, "Worker callback %s is not a function", msg->callback); } else { assert(!ejs->exception); argv[0] = event; ejsRunFunction(ejs, callback, worker, 1, argv); } if (msg->callbackSlot == ES_Worker_onclose) { assert(!worker->inside); worker->state = EJS_WORKER_COMPLETE; mprTrace(5, "Worker.doMessage: complete"); /* Worker and insider interpreter are now eligible for garbage collection */ removeWorker(worker); } mprSignalDispatcher(ejs->dispatcher); worker->event = 0; return 0; }
MprVar espCreateObjVar(char *name, int hashSize) { return ejsCreateObj(name, hashSize); }