Exemple #1
0
/*
 *  Public routine to set the error message. Caller MUST NOT free.
 */
char *ejsGetErrorMsg(Ejs *ejs, int withStack)
{
    EjsVar      *message, *stack, *error;
    cchar       *name;
    char        *buf;

    if (ejs->flags & EJS_FLAG_EMPTY) {
        return "";
    }

    error = (EjsVar*) ejs->exception;
    message = stack = 0;
    name = 0;

    if (error) {
        name = error->type->qname.name;
        if (ejsIsA(ejs, error, ejs->errorType)) {
            message = ejsGetProperty(ejs, error, ES_Error_message);
            stack = ejsGetProperty(ejs, error, ES_Error_stack);

        } else if (ejsIsString(error)) {
            name = "Error";
            message = error;

        } else if (ejsIsNumber(error)) {
            name = "Error";
            message = error;
            
        } else if (error == (EjsVar*) ejs->stopIterationType) {
            name = "StopIteration";
            message = (EjsVar*) ejsCreateString(ejs, "Uncaught StopIteration exception");
        }
    }
    if (!withStack) {
        stack = 0;
    }

    if (stack && ejsIsString(stack) && message && ejsIsString(message)){
        buf = mprAsprintf(ejs, -1, "%s Exception: %s\nStack:\n%s", name, ((EjsString*) message)->value, 
            ((EjsString*) stack)->value);

    } else if (message && ejsIsString(message)){
        buf = mprAsprintf(ejs, -1, "%s: %s", name, ((EjsString*) message)->value);

    } else if (message && ejsIsNumber(message)){
        buf = mprAsprintf(ejs, -1, "%s: %d", name, ((EjsNumber*) message)->value);
        
    } else {
        if (error) {
            buf = mprStrdup(ejs, "Unknown exception object type");
        } else {
            buf = mprStrdup(ejs, "");
        }
    }
    mprFree(ejs->errorMsg);
    ejs->errorMsg = buf;
    return buf;
}
Exemple #2
0
static void setHttpPipeline(Ejs *ejs, EjsHttpServer *sp) 
{
    EjsString       *vs;
    HttpHost        *host;
    HttpRoute       *route;
    Http            *http;
    HttpStage       *stage;
    cchar           *name;
    int             i;

    assure(sp->endpoint);
    http = sp->endpoint->http;
    host = mprGetFirstItem(sp->endpoint->hosts);
    route = mprGetFirstItem(host->routes);

    if (sp->outgoingStages) {
        httpClearRouteStages(route, HTTP_STAGE_TX);
        for (i = 0; i < sp->outgoingStages->length; i++) {
            vs = ejsGetProperty(ejs, sp->outgoingStages, i);
            if (vs && ejsIs(ejs, vs, String)) {
                name = vs->value;
                if (httpLookupStage(http, name) == 0) {
                    ejsThrowArgError(ejs, "Cannot find pipeline stage name %s", name);
                    return;
                }
                httpAddRouteFilter(route, name, NULL, HTTP_STAGE_TX);
            }
        }
    }
    if (sp->incomingStages) {
        httpClearRouteStages(route, HTTP_STAGE_RX);
        for (i = 0; i < sp->incomingStages->length; i++) {
            vs = ejsGetProperty(ejs, sp->incomingStages, i);
            if (vs && ejsIs(ejs, vs, String)) {
                name = vs->value;
                if (httpLookupStage(http, name) == 0) {
                    ejsThrowArgError(ejs, "Cannot find pipeline stage name %s", name);
                    return;
                }
                httpAddRouteFilter(route, name, NULL, HTTP_STAGE_RX);
            }
        }
    }
    if (sp->connector) {
        if ((stage = httpLookupStage(http, sp->connector)) == 0) {
            ejsThrowArgError(ejs, "Cannot find pipeline stage name %s", sp->connector);
            return;
        }
        route->connector = stage;
    }
}
Exemple #3
0
/**
    Get a serialized string representation of a variable using JSON encoding.
    @return Returns a string variable or null if an exception is thrown.
 */
EjsString *ejsToJson(Ejs *ejs, EjsVar *vp)
{
    EjsFunction     *fn;
    EjsString       *result;

    if (vp == 0) {
        return ejsCreateString(ejs, "undefined");
    }
    if (vp->jsonVisited) {
        return ejsCreateString(ejs, "this");
    }
    vp->jsonVisited = 1;

    /*
     *  Types can provide a toJSON method, a serializeVar helper. If neither are provided, toString is used as a fall-back.
     */
    fn = (EjsFunction*) ejsGetProperty(ejs, (EjsVar*) vp->type, ES_Object_toJSON);
    if (ejsIsFunction(fn)) {
        result = (EjsString*) ejsRunFunction(ejs, fn, vp, 0, NULL);
    } else {
        result = ejsToString(ejs, vp);
    }
    vp->jsonVisited = 0;
    return result;
}
Exemple #4
0
/**
    Get a string representation of a variable.
    @return Returns a string variable or null if an exception is thrown.
 */
EjsString *ejsToString(Ejs *ejs, EjsVar *vp)
{
    EjsFunction     *fn;

    if (vp == 0) {
        return ejsCreateString(ejs, "undefined");
    } else if (ejsIsString(vp)) {
        return (EjsString*) vp;
    }

    /*
     *  Types can provide a toString method or a castVar helper
     */
    if (vp->type->helpers->getProperty != getProperty) { 
        fn = (EjsFunction*) ejsGetProperty(ejs, (EjsVar*) vp->type, ES_Object_toString);
        if (ejsIsFunction(fn)) {
            return (EjsString*) ejsRunFunction(ejs, fn, vp, 0, NULL);
        }
    }
    if (vp->type->helpers->castVar) {
        return (EjsString*) (vp->type->helpers->castVar)(ejs, vp, ejs->stringType);
    }
    ejsThrowInternalError(ejs, "CastVar helper not defined for type \"%s\"", vp->type->qname.name);
    return 0;
}
Exemple #5
0
EjsVar *ejsCreateException(Ejs *ejs, int slot, cchar *fmt, va_list fmtArgs)
{
    EjsType     *type;
    EjsVar      *error;
    char        *buf;

    if (ejs->exception) {
        buf = mprVasprintf(ejs, 0, fmt, fmtArgs);
        mprError(ejs, "Double exception: %s", buf);
        mprFree(buf);
        return ejs->exception;
    }
    if (!ejs->initialized || (ejs->flags & EJS_FLAG_EMPTY)) {
        buf = mprVasprintf(ejs, 0, fmt, fmtArgs);
        mprError(ejs, "Exception: %s", buf);
        mprFree(buf);
        return ejs->exception;
    }
    type = (EjsType*) ejsGetProperty(ejs, ejs->global, slot);
    if (type == 0) {
        type = ejs->errorType;
    }
    error = createException(ejs, type, fmt, fmtArgs);
    if (error) {
        ejsThrowException(ejs, error);
    }
    return error;
}
Exemple #6
0
EjsVar *ejsCreateInstance(Ejs *ejs, EjsType *type, int argc, EjsVar **argv)
{
    EjsFunction     *fun;
    EjsVar          *vp;
    int             slotNum;

    mprAssert(type);

    vp = ejsCreateVar(ejs, type, 0);
    if (vp == 0) {
        ejsThrowMemoryError(ejs);
        return 0;
    }

    if (type->hasConstructor) {
        slotNum = type->block.numInherited;
        fun = (EjsFunction*) ejsGetProperty(ejs, (EjsVar*) type, slotNum);
        if (fun == 0) {
            return 0;
        }
        if (!ejsIsFunction(fun)) {
            return 0;
        }

        vp->permanent = 1;
        ejsRunFunction(ejs, fun, vp, argc, argv);
        vp->permanent = 0;
    }

    return vp;
}
Exemple #7
0
/*
 *  Get a variable by name. If vp is specified, it contains an explicit object in which to search for the variable name. 
 *  Otherwise, the full execution scope is consulted. The lookup fields will be set as residuals.
 */
EjsVar *ejsGetVarByName(Ejs *ejs, EjsVar *vp, EjsName *name, EjsLookup *lookup)
{
    EjsVar  *result;
    int     slotNum;

    mprAssert(ejs);
    mprAssert(name);

    //  OPT - really nice to remove this
    if (vp && vp->type->helpers->getPropertyByName) {
        result = (*vp->type->helpers->getPropertyByName)(ejs, vp, name);
        if (result) {
            return result;
        }
    }

    if (vp) {
        slotNum = ejsLookupVar(ejs, vp, name, lookup);
    } else {
        slotNum = ejsLookupScope(ejs, name, lookup);
    }
    if (slotNum < 0) {
        return 0;
    }
    return ejsGetProperty(ejs, lookup->obj, slotNum);
}
Exemple #8
0
/*  
    function send(...content): Number
 */
static EjsNumber *ws_send(Ejs *ejs, EjsWebSocket *ws, int argc, EjsObj **argv)
{
    EjsArray        *args;
    EjsByteArray    *ba;
    EjsAny          *arg;
    ssize           nbytes;
    int             i;

    args = (EjsArray*) argv[0];
    if (ws->conn->state < HTTP_STATE_PARSED && !waitForHttpState(ws, HTTP_STATE_PARSED, -1, 1)) {
        return ESV(null);
    }
    nbytes = 0;
    for (i = 0; i < args->length; i++) {
        if ((arg = ejsGetProperty(ejs, args, i)) != 0) {
            if (ejsIs(ejs, arg, ByteArray)) {
                ba = (EjsByteArray*) arg;
                nbytes = ejsGetByteArrayAvailableData(ba);
                nbytes = httpSendBlock(ws->conn, WS_MSG_BINARY, (cchar*) &ba->value[ba->readPosition], nbytes, HTTP_BLOCK);
            } else {
                nbytes = httpSend(ws->conn, ejsToMulti(ejs, arg));
            }
            if (nbytes < 0) {
                return ESV(null);
            }
        }
    }
    return ejsCreateNumber(ejs, (MprNumber) nbytes);
}
Exemple #9
0
/*  
    function setLimits(limits: Object): Void
 */
static EjsObj *hs_setLimits(Ejs *ejs, EjsHttpServer *sp, int argc, EjsObj **argv)
{
    EjsObj      *vp, *app, *cache, *cacheLimits;
    HttpLimits  *limits;

    if (sp->limits == 0) {
        sp->limits = ejsCreateEmptyPot(ejs);
        limits = (sp->endpoint) ? sp->endpoint->limits : ejs->http->serverLimits;
        assure(limits);
        ejsGetHttpLimits(ejs, sp->limits, limits, 1);
    }
    ejsBlendObject(ejs, sp->limits, argv[0], EJS_BLEND_OVERWRITE);
    if (sp->endpoint) {
        limits = (sp->endpoint) ? sp->endpoint->limits : ejs->http->serverLimits;
        ejsSetHttpLimits(ejs, limits, sp->limits, 1);
    }
    if ((vp = ejsGetPropertyByName(ejs, sp->limits, EN("sessionTimeout"))) != 0) {
        app = ejsGetPropertyByName(ejs, ejs->global, N("ejs", "App"));
        cache = ejsGetProperty(ejs, app, ES_App_cache);
        if (cache && cache != ESV(null)) {
            cacheLimits = ejsCreateEmptyPot(ejs);
            ejsSetPropertyByName(ejs, cacheLimits, EN("lifespan"), vp);
            ejsCacheSetLimits(ejs, cache, cacheLimits);
        }
    }
    return 0;
}
Exemple #10
0
static void setupTrace(Ejs *ejs, HttpTrace *trace, int dir, EjsObj *options)
{
    EjsArray    *extensions;
    EjsObj      *ext;
    HttpTrace   *tp;
    int         i, level, *levels;

    tp = &trace[dir];
    levels = tp->levels;
    if ((level = getNumOption(ejs, options, "all")) >= 0) {
        for (i = 0; i < HTTP_TRACE_MAX_ITEM; i++) {
            levels[i] = level;
        }
    } else {
        levels[HTTP_TRACE_CONN] = getNumOption(ejs, options, "conn");
        levels[HTTP_TRACE_FIRST] = getNumOption(ejs, options, "first");
        levels[HTTP_TRACE_HEADER] = getNumOption(ejs, options, "headers");
        levels[HTTP_TRACE_BODY] = getNumOption(ejs, options, "body");
    }
    tp->size = getNumOption(ejs, options, "size");
    if ((extensions = (EjsArray*) ejsGetPropertyByName(ejs, options, EN("include"))) != 0) {
        if (!ejsIs(ejs, extensions, Array)) {
            ejsThrowArgError(ejs, "include is not an array");
            return;
        }
        tp->include = mprCreateHash(0, 0);
        for (i = 0; i < extensions->length; i++) {
            if ((ext = ejsGetProperty(ejs, extensions, i)) != 0) {
                mprAddKey(tp->include, ejsToMulti(ejs, ejsToString(ejs, ext)), "");
            }
        }
    }
    if ((extensions = (EjsArray*) ejsGetPropertyByName(ejs, options, EN("exclude"))) != 0) {
        if (!ejsIs(ejs, extensions, Array)) {
            ejsThrowArgError(ejs, "exclude is not an array");
            return;
        }
        tp->exclude = mprCreateHash(0, 0);
        for (i = 0; i < extensions->length; i++) {
            if ((ext = ejsGetProperty(ejs, extensions, i)) != 0) {
                mprAddKey(tp->exclude, ejsToMulti(ejs, ejsToString(ejs, ext)), MPR->emptyString);
            }
        }
    }
}
Exemple #11
0
/*
    function secure(keyFile: Path, certFile: Path!, protocols: Array? = null, ciphers: Array? = null): Void
 */
static EjsObj *hs_secure(Ejs *ejs, EjsHttpServer *sp, int argc, EjsObj **argv)
{
#if ME_COM_SSL
    EjsArray    *protocols;
    cchar       *token;
    int         mask, protoMask, i;

    if (sp->ssl == 0 && ((sp->ssl = mprCreateSsl(1)) == 0)) {
        return 0;
    }
    if (!ejsIs(ejs, argv[0], Null)) {
        mprSetSslKeyFile(sp->ssl, ejsToMulti(ejs, argv[0]));
    }
    if (!ejsIs(ejs, argv[1], Null)) {
        mprSetSslCertFile(sp->ssl, ejsToMulti(ejs, argv[1]));
    }
    if (argc >= 3 && ejsIs(ejs, argv[2], Array)) {
        protocols = (EjsArray*) argv[2];
        protoMask = 0;
        for (i = 0; i < protocols->length; i++) {
            token = ejsToMulti(ejs, ejsGetProperty(ejs, protocols, i));
            mask = -1;
            if (*token == '-') {
                token++;
                mask = 0;
            } else if (*token == '+') {
                token++;
            }
            if (scaselesscmp(token, "SSLv2") == 0) {
                protoMask &= ~(MPR_PROTO_SSLV2 & ~mask);
                protoMask |= (MPR_PROTO_SSLV2 & mask);

            } else if (scaselesscmp(token, "SSLv3") == 0) {
                protoMask &= ~(MPR_PROTO_SSLV3 & ~mask);
                protoMask |= (MPR_PROTO_SSLV3 & mask);

            } else if (scaselesscmp(token, "TLSv1") == 0) {
                protoMask &= ~(MPR_PROTO_TLSV1 & ~mask);
                protoMask |= (MPR_PROTO_TLSV1 & mask);

            } else if (scaselesscmp(token, "ALL") == 0) {
                protoMask &= ~(MPR_PROTO_ALL & ~mask);
                protoMask |= (MPR_PROTO_ALL & mask);
            }
        }
        mprSetSslProtocols(sp->ssl, protoMask);
    }
    if (argc >= 4 && ejsIs(ejs, argv[3], Array)) {
        mprSetSslCiphers(sp->ssl, ejsToMulti(ejs, argv[3]));
    }
#else
    ejsThrowReferenceError(ejs, "SSL support was not included in the build");
#endif
    return 0;
}
Exemple #12
0
/*  
    Write data to the file
    function write(data: Object): Number
 */
PUBLIC EjsObj *writeFile(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv)
{
    EjsArray        *args;
    EjsByteArray    *ap;
    EjsObj          *vp;
    EjsString       *str;
    cchar           *buf;
    ssize           len, written;
    int             i;

    assert(argc == 1 && ejsIs(ejs, argv[0], Array));

    args = (EjsArray*) argv[0];

    if (!(fp->mode & EJS_FILE_WRITE)) {
        ejsThrowStateError(ejs, "File not opened for writing");
        return 0;
    }
    written = 0;

    for (i = 0; i < args->length; i++) {
        vp = ejsGetProperty(ejs, (EjsObj*) args, i);
        assert(vp);
        switch (TYPE(vp)->sid) {
        case S_ByteArray:
            ap = (EjsByteArray*) vp;
            //  TODO UNICODE ENCODING
            buf = (cchar*) &ap->value[ap->readPosition];
            len = ap->writePosition - ap->readPosition;
            break;

        case S_String: // UNICODE
#if UNICODE && FUTURE
            buf = awtom(((EjsString*) vp)->value, &len);
#else
            buf = ((EjsString*) vp)->value;
            len = ((EjsString*) vp)->length;
#endif
            break;

        default:
            str = ejsToString(ejs, vp);
            buf = awtom(((EjsString*) str)->value, &len);
            break;
        }
        if (mprWriteFile(fp->file, buf, len) != len) {
            ejsThrowIOError(ejs, "Cannot write to %s", fp->path);
            return 0;
        }
        written += len;
        /* Use GC to free buf as it may not be allocated */
    }
    return (EjsObj*) ejsCreateNumber(ejs, (MprNumber) written);
}
Exemple #13
0
/*
    function emit(level: Number, ...data): Number
 */
static EjsNumber *lf_emit(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv)
{
    EjsArray        *args;
    EjsByteArray    *ap;
    EjsObj          *vp;
    EjsString       *str;
    char            *msg, *arg;
    ssize           len, written;
    int             i, level, paused;

    assure(argc >= 2 && ejsIs(ejs, argv[1], Array));

    level = ejsGetInt(ejs, argv[0]);
    args = (EjsArray*) argv[1];
    written = 0;
    msg = 0;
    paused = ejsBlockGC(ejs);

    for (i = 0; i < args->length; i++) {
        vp = ejsGetProperty(ejs, args, i);
        assure(vp);
        switch (TYPE(vp)->sid) {
        case S_ByteArray:
            ap = (EjsByteArray*) vp;
            //  TODO ENCODING
            arg = (char*) &ap->value[ap->readPosition];
            len = ap->writePosition - ap->readPosition;
            break;

        case S_String:
            //  MOB - use NULL instead of &len
            arg = awtom(((EjsString*) vp)->value, &len);
            break;

        default:
            str = ejsToString(ejs, vp);
            //  MOB - use NULL instead of &len
            arg = awtom(((EjsString*) str)->value, &len);
            break;
        }
        msg = srejoin(msg, arg, NULL);
    }
    if (msg) {
        mprRawLog(level, "%s", msg);
        written += slen(msg);
    }
    ejsUnblockGC(ejs, paused);
    return ejsCreateNumber(ejs, (MprNumber) slen(msg));
}
Exemple #14
0
static EjsVar *booleanConstructor(Ejs *ejs, EjsBoolean *bp, int argc, EjsVar **argv)
{
    EjsArray    *args;
    EjsVar      *vp;

    mprAssert(argc == 0 || (argc == 1 && ejsIsArray(argv[0])));

    if (argc == 1) {
        args = (EjsArray*) argv[0];

        vp = ejsGetProperty(ejs, (EjsVar*) args, 0);
        if (vp) {
            /* Change the bp value */
            bp = ejsToBoolean(ejs, vp);
        }
    }
    return (EjsVar*) bp;
}
Exemple #15
0
EjsAny *ejsCreateException(Ejs *ejs, int slot, cchar *fmt, va_list fmtArgs)
{
    EjsType     *type;
    EjsAny      *error;

    if (ejs->exception) {
        mprLog("ejs vm", 0, "Double exception: %s", sfmtv(fmt, fmtArgs));
        return ejs->exception;
    }
    type = (ejs->initialized) ? ejsGetProperty(ejs, ejs->global, slot) : NULL;
    if (type == 0) {
        type = EST(Error);
    }
    error = createException(ejs, type, fmt, fmtArgs);
    if (error) {
        ejsThrowException(ejs, error);
    }
    return error;
}
Exemple #16
0
/*  
    Prepare form data as a series of key-value pairs. Data is formatted according to www-url-encoded specs by 
    mprSetHttpFormData. Objects are flattened into a one level key/value pairs. Keys can have embedded "." separators.
    E.g.  name=value&address=77%20Park%20Lane
 */
static void prepForm(Ejs *ejs, EjsHttp *hp, cchar *prefix, EjsObj *data)
{
    EjsName     qname;
    EjsObj      *vp;
    EjsString   *value;
    cchar       *key, *sep, *vstr;
    char        *encodedKey, *encodedValue, *newPrefix, *newKey;
    int         i, count;

    count = ejsGetLength(ejs, data);
    for (i = 0; i < count; i++) {
        if (ejsIs(ejs, data, Array)) {
            key = itos(i);
        } else {
            qname = ejsGetPropertyName(ejs, data, i);
            key = ejsToMulti(ejs, qname.name);
        }
        vp = ejsGetProperty(ejs, data, i);
        if (vp == 0) {
            continue;
        }
        if (ejsGetLength(ejs, vp) > 0) {
            if (prefix) {
                newPrefix = sfmt("%s.%s", prefix, key);
                prepForm(ejs, hp, newPrefix, vp);
            } else {
                prepForm(ejs, hp, key, vp);
            }
        } else {
            value = ejsToString(ejs, vp);
            sep = (mprGetBufLength(hp->requestContent) > 0) ? "&" : "";
            if (prefix) {
                newKey = sjoin(prefix, ".", key, NULL);
                encodedKey = mprUriEncode(newKey, MPR_ENCODE_URI_COMPONENT); 
            } else {
                encodedKey = mprUriEncode(key, MPR_ENCODE_URI_COMPONENT);
            }
            vstr = ejsToMulti(ejs, value);
            encodedValue = mprUriEncode(vstr, MPR_ENCODE_URI_COMPONENT);
            mprPutToBuf(hp->requestContent, "%s%s=%s", sep, encodedKey, encodedValue);
        }
    }
}
Exemple #17
0
/*
 *  Get a property given a name.
 */
EjsVar *ejsGetPropertyByName(Ejs *ejs, EjsVar *vp, EjsName *name)
{
    int     slotNum;

    mprAssert(ejs);
    mprAssert(vp);
    mprAssert(name);

    if (vp->type->helpers->getPropertyByName) {
        return (vp->type->helpers->getPropertyByName)(ejs, vp, name);
    }

    /*
     *  Fall back and use a two-step lookup and get
     */
    slotNum = ejsLookupProperty(ejs, vp, name);
    if (slotNum < 0) {
        return 0;
    }
    return ejsGetProperty(ejs, vp, slotNum);
}
Exemple #18
0
/*  
    Join uri segments
    function join(...others): Uri
 */
static EjsUri *uri_join(Ejs *ejs, EjsUri *up, int argc, EjsObj **argv)
{
    EjsUri      *result;
    EjsObj      *arg;
    EjsArray    *args;
    HttpUri     *uri, *other, *oldUri;
    int         i;

    args = (EjsArray*) argv[0];
    result = cloneUri(ejs, up, 0);
    uri = result->uri;
    for (i = 0; i < args->length; i++) {
        arg = ejsGetProperty(ejs, args, i);
        if ((other = toHttpUri(ejs, arg, 0)) == NULL) {
            return 0;
        }
        oldUri = uri;
        uri = httpJoinUri(oldUri, 1, &other);
    }
    result->uri = uri;
    return result;
}
Exemple #19
0
EjsVar *ejsCreateException(Ejs *ejs, int slot, cchar *fmt, va_list fmtArgs)
{
    EjsType     *type;
    EjsVar      *error;
    char        *buf;

#if DEBUG_IDE
    mprBreakpoint(0, 0);
#endif

    mprAssert(ejs->exception == 0);

    if (ejs->exception) {
        mprAllocVsprintf(ejs, &buf, 0, fmt, fmtArgs);
        mprError(ejs, "Double exception: %s", buf);
        return ejs->exception;
    }

    if (!ejs->initialized || (ejs->flags & EJS_FLAG_EMPTY)) {
        mprAllocVsprintf(ejs, &buf, 0, fmt, fmtArgs);
        mprError(ejs, "Exception: %s", buf);
        return ejs->exception;
    }

    type = (EjsType*) ejsGetProperty(ejs, ejs->global, slot);

    if (type == 0) {
        type = ejs->errorType;
    }

    error = createException(ejs, type, fmt, fmtArgs);

    if (error) {
        ejsThrowException(ejs, error);
    }
    return error;
}
Exemple #20
0
/*
    Cast the operand to the specified type

    function cast(type: Type) : Object
 */
static EjsAny *castError(Ejs *ejs, EjsError *error, EjsType *type)
{
    EjsString   *stack, *msg;
    EjsString   *us;
    char        *buf;

    switch (type->sid) {
    case S_Boolean:
        return ejsCreateBoolean(ejs, 1);

    case S_String:
        stack = (EjsString*) ejsRunFunctionBySlot(ejs, error, ES_Error_formatStack, 0, NULL);
        us = ejsIs(ejs, stack, String) ? stack : ESV(empty);
        msg = ejsGetProperty(ejs, error, ES_Error_message);
        if ((buf = sfmt("%@ Exception: %@\nStack:\n%@\n", TYPE(error)->qname.name, msg, us)) == NULL) {
            ejsThrowMemoryError(ejs);
        }
        return ejsCreateStringFromAsc(ejs, buf);

    default:
        ejsThrowTypeError(ejs, "Unknown type");
    }
    return 0;
}
Exemple #21
0
/*
    Get a variable by name. If obj is specified, it contains an explicit object in which to search for the variable name. 
    Otherwise, the full execution scope is consulted. The lookup fields will be set as residuals.
 */
EjsAny *ejsGetVarByName(Ejs *ejs, EjsAny *obj, EjsName name, EjsLookup *lookup)
{
    EjsObj  *result;
    int     slotNum;

    assert(ejs);

    //  OPT - really nice to remove this
    //  OPT -- perhaps delegate the logic below down into a getPropertyByName?
    if (obj && TYPE(obj)->helpers.getPropertyByName) {
        if ((result = (TYPE(obj)->helpers.getPropertyByName)(ejs, obj, name)) != 0) {
            return result;
        }
    }
    if (obj) {
        slotNum = ejsLookupVar(ejs, obj, name, lookup);
    } else {
        slotNum = ejsLookupScope(ejs, name, lookup);
    }
    if (slotNum < 0) {
        return 0;
    }
    return ejsGetProperty(ejs, lookup->obj, slotNum);
}
Exemple #22
0
static EjsRequest *createRequest(EjsHttpServer *sp, HttpConn *conn)
{
    Ejs             *ejs;
    EjsRequest      *req;
    EjsPath         *documents;
    cchar           *dir;

    ejs = sp->ejs;
    documents = ejsGetProperty(ejs, sp, ES_ejs_web_HttpServer_documents);
    if (ejsIs(ejs, documents, Path)) {
        dir = documents->value;
    } else {
        /* Safety fall back */
        dir = conn->rx->route->home;
    }
    req = ejsCreateRequest(ejs, sp, conn, dir);
    httpSetConnContext(conn, req);

#if FUTURE
    if (sp->pipe) {
        def = ejsRunFunction(ejs, sp->createPipeline,
        if ((vp = ejsGetPropertyByName(ejs, def, ejsName(&name, "", "handler"))) != 0) {
        handler = ejsToMulti(ejs, vp);
        }
Exemple #23
0
static void receiveRequest(EjsRequest *req, MprEvent *event)
{
    Ejs             *ejs;
    EjsAny          *argv[1];
    EjsFunction     *onrequest;
    HttpConn        *conn;

    conn = req->conn;
    ejs = req->ejs;
    assert(ejs);

    onrequest = ejsGetProperty(ejs, req->server, ES_ejs_web_HttpServer_onrequest);
    if (!ejsIsFunction(ejs, onrequest)) {
        ejsThrowStateError(ejs, "HttpServer.onrequest is not a function");
        return;
    }
    argv[0] = req;
    ejsRunFunction(ejs, onrequest, req->server, 1, argv);
    if (conn->state == HTTP_STATE_BEGIN) {
        conn->ejs = 0;
        httpUsePrimary(conn);
    }
    httpEnableConnEvents(conn);
}
Exemple #24
0
static EjsString *serialize(Ejs *ejs, EjsAny *vp, Json *json)
{
    EjsName     qname;
    EjsFunction *fn;
    EjsString   *result, *sv;
    EjsTrait    *trait;
    EjsObj      *pp, *obj, *replacerArgs[2];
    wchar       *cp;
    cchar       *key;
    int         c, isArray, i, count, slotNum, quotes;

    /*
        The main code below can handle Arrays, Objects, objects derrived from Object and also native classes with properties.
        All others just use toString.
     */
    count = ejsIsPot(ejs, vp) ? ejsGetLength(ejs, vp) : 0;
    if (count == 0 && TYPE(vp) != ESV(Object) && TYPE(vp) != ESV(Array)) {
        //  OPT - need some flag for this test.
        if (!ejsIsDefined(ejs, vp) || ejsIs(ejs, vp, Boolean) || ejsIs(ejs, vp, Number)) {
            return ejsToString(ejs, vp);
        } else if (json->regexp) {
            return ejsToString(ejs, vp);
        } else {
            return ejsToLiteralString(ejs, vp);
        }
    }
    obj = vp;
    json->nest++;
    if (json->buf == 0) {
        json->buf = mprCreateBuf(0, 0);
        mprAddRoot(json->buf);
    }
    isArray = ejsIs(ejs, vp, Array);
    mprPutCharToWideBuf(json->buf, isArray ? '[' : '{');
    if (json->pretty) {
        mprPutCharToWideBuf(json->buf, '\n');
    }
    if (++ejs->serializeDepth <= json->depth && !VISITED(obj)) {
        SET_VISITED(obj, 1);
        for (slotNum = 0; slotNum < count && !ejs->exception; slotNum++) {
            trait = ejsGetPropertyTraits(ejs, obj, slotNum);
            if (trait && (trait->attributes & (EJS_TRAIT_HIDDEN | EJS_TRAIT_DELETED | EJS_FUN_INITIALIZER | 
                    EJS_FUN_MODULE_INITIALIZER)) && !json->hidden) {
                continue;
            }
            pp = ejsGetProperty(ejs, obj, slotNum);
            if (ejs->exception) {
                SET_VISITED(obj, 0);
                json->nest--;
                return 0;
            }
            if (pp == 0) {
                continue;
            }
            if (isArray) {
                key = itos(slotNum);
                qname.name = ejsCreateStringFromAsc(ejs, key);
                qname.space = ESV(empty);
            } else {
                qname = ejsGetPropertyName(ejs, vp, slotNum);
            }

            quotes = json->quotes;
            if (!quotes) {
                //  UNICODE
                for (cp = qname.name->value; cp < &qname.name->value[qname.name->length]; cp++) {
                    if (!isalnum((uchar) *cp) && *cp != '_') {
                        quotes = 1;
                        break;
                    }
                }
            }
            if (json->pretty) {
                for (i = 0; i < ejs->serializeDepth; i++) {
                    mprPutStringToWideBuf(json->buf, json->indent);
                }
            }
            if (!isArray) {
                if (json->namespaces) {
                    if (qname.space != ESV(empty)) {
                        mprPutToBuf(json->buf, "\"%@\"::", qname.space);
                    }
                }
                if (quotes) {
                    mprPutCharToWideBuf(json->buf, '"');
                }
                for (cp = qname.name->value; cp && *cp; cp++) {
                    c = *cp;
                    if (c == '"' || c == '\\') {
                        mprPutCharToWideBuf(json->buf, '\\');
                        mprPutCharToWideBuf(json->buf, c);
                    } else {
                        mprPutCharToWideBuf(json->buf, c);
                    }
                }
                if (quotes) {
                    mprPutCharToWideBuf(json->buf, '"');
                }
                mprPutCharToWideBuf(json->buf, ':');
                if (json->pretty) {
                    mprPutCharToWideBuf(json->buf, ' ');
                }
            }
            fn = (EjsFunction*) ejsGetPropertyByName(ejs, TYPE(pp)->prototype, N(NULL, "toJSON"));
            // OPT - check that this is going directly to serialize most of the time
            if (!ejsIsFunction(ejs, fn) || (fn->isNativeProc && fn->body.proc == (EjsProc) ejsObjToJSON)) {
                sv = serialize(ejs, pp, json);
            } else {
                sv = (EjsString*) ejsRunFunction(ejs, fn, pp, 1, &json->options);
            }
            if (sv == 0 || !ejsIs(ejs, sv, String)) {
                if (ejs->exception) {
                    ejsThrowTypeError(ejs, "Cannot serialize property %@", qname.name);
                    SET_VISITED(obj, 0);
                    return 0;
                }
            } else {
                if (json->replacer) {
                    replacerArgs[0] = (EjsObj*) qname.name; 
                    replacerArgs[1] = (EjsObj*) sv; 

                    /* function replacer(key: String, value: String): String */
                    sv = ejsRunFunction(ejs, json->replacer, obj, 2, (EjsObj**) replacerArgs);
                }
                mprPutBlockToBuf(json->buf, sv->value, sv->length * sizeof(wchar));
            }
            if ((slotNum + 1) < count || json->commas) {
                mprPutCharToWideBuf(json->buf, ',');
            }
            if (json->pretty) {
                mprPutCharToWideBuf(json->buf, '\n');
            }
        }
        SET_VISITED(obj, 0);
    }
    --ejs->serializeDepth; 
    if (json->pretty) {
        for (i = ejs->serializeDepth; i > 0; i--) {
            mprPutStringToWideBuf(json->buf, json->indent);
        }
    }
    mprPutCharToWideBuf(json->buf, isArray ? ']' : '}');
    mprAddNullToWideBuf(json->buf);

    if (--json->nest == 0) {
        result = ejsCreateString(ejs, mprGetBufStart(json->buf), mprGetBufLength(json->buf) / sizeof(wchar));
        mprRemoveRoot(json->buf);
    } else {
        result = 0;
    }
    return result;
}
Exemple #25
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;
}
Exemple #26
0
/*
    Get the current exception error. May be an Error object or may be any other object that is thrown.
    Caller must NOT free.
 */
cchar *ejsGetErrorMsg(Ejs *ejs, int withStack)
{
    EjsString   *str, *tag, *msg, *message;
    EjsAny      *stack, *error, *saveException;
    char        *buf, *stackStr;

    error = ejs->exception;
    message = 0;
    stack = 0;
    tag = NULL;

    if (error) {
        tag = TYPE(error)->qname.name;
        if (ejsIs(ejs, error, Error)) {
            message = ejsGetProperty(ejs, error, ES_Error_message);
            if (withStack && ejs->initialized && ejs->state) {
                saveException = ejs->exception;
                ejsClearException(ejs);
                stack = ejsRunFunctionBySlot(ejs, error, ES_Error_formatStack, 0, NULL);
                ejsThrowException(ejs, saveException);
            }

        } else if (ejsIs(ejs, error, String)) {
            tag = ejsCreateStringFromAsc(ejs, "Error");
            message = (EjsString*) error;

        } else if (ejsIs(ejs, error, Number)) {
            tag = ejsCreateStringFromAsc(ejs, "Error");
            message = (EjsString*) error;
            
        } else if (error == EST(StopIteration)) {
            message = ejsCreateStringFromAsc(ejs, "Uncaught StopIteration exception");
        }
    }
    if (message == ESV(null) || message == 0) {
        msg = ejsCreateStringFromAsc(ejs, "Exception");
    } else{
        msg = ejsToString(ejs, message);
    }
    if (ejsIs(ejs, error, Error)) {
        stackStr = (stack) ? ejsToMulti(ejs, stack) : 0;
        if (stackStr && *stackStr) {
            buf = sfmt("%@: %@\nStack:\n%s", tag, msg, (stack) ? ejsToMulti(ejs, stack) : "");
        } else {
            buf = sfmt("%@: %@", tag, msg);
        }

    } else if (message && ejsIs(ejs, message, String)){
        buf = sfmt("%@: %@", tag, msg);

    } else if (message && ejsIs(ejs, message, Number)){
        buf = sfmt("%@: %g", tag, ((EjsNumber*) msg)->value);
        
    } else if (error) {
        EjsObj *saveException = ejs->exception;
        ejs->exception = 0;
        str = ejsToString(ejs, error);
        buf = sclone(ejsToMulti(ejs, str));
        ejs->exception = saveException;

    } else {
        buf = sclone("");
    }
    ejs->errorMsg = buf;
    return buf;
}
Exemple #27
0
/*
    function listen(endpoint): Void

    An endpoint can be either a "port" or "ip:port", or null. If hosted, this call does little -- just add to the
    ejs->httpServers list.
 */
static EjsVoid *hs_listen(Ejs *ejs, EjsHttpServer *sp, int argc, EjsObj **argv)
{
    HttpEndpoint    *endpoint;
    HttpHost        *host;
    HttpRoute       *route;
    EjsString       *address;
    EjsObj          *loc;
    EjsPath         *documents;

    if (!sp->hosted) {
        loc = (argc >= 1) ? argv[0] : ESV(null);
        if (loc != ESV(null)) {
            address = ejsToString(ejs, loc);
            //  TODO should permit https://IP:PORT
            mprParseSocketAddress(address->value, &sp->ip, &sp->port, NULL, 0);
        } else {
            address = 0;
        }
        if (address == 0) {
            ejsThrowArgError(ejs, "Missing listen endpoint");
            return 0;
        }
        if (sp->endpoint) {
            httpDestroyEndpoint(sp->endpoint);
            sp->endpoint = 0;
        }
        /*
            The endpoint uses the ejsDispatcher. This is VERY important. All connections will inherit this also.
            This serializes all activity on one dispatcher.
         */
        if ((endpoint = httpCreateEndpoint(sp->ip, sp->port, ejs->dispatcher)) == 0) {
            ejsThrowIOError(ejs, "Cannot create Http endpoint object");
            return 0;
        }
        sp->endpoint = endpoint;
        host = httpCreateHost(NULL);
        httpSetHostName(host, sfmt("%s:%d", sp->ip, sp->port));
        route = httpCreateConfiguredRoute(host, 1);

        httpAddRouteMethods(route, "DELETE, HEAD, OPTIONS, PUT");
        httpAddRouteHandler(route, "ejsHandler", "");
        httpSetRouteTarget(route, "run", 0);
        httpFinalizeRoute(route);

        httpSetHostDefaultRoute(host, route);
        httpAddHostToEndpoint(endpoint, host);

        if (sp->limits) {
            ejsSetHttpLimits(ejs, endpoint->limits, sp->limits, 1);
        }
        if (sp->incomingStages || sp->outgoingStages || sp->connector) {
            setHttpPipeline(ejs, sp);
        }
        if (sp->ssl) {
            httpSecureEndpoint(endpoint, sp->ssl);
        }
        if (sp->name) {
            httpSetHostName(host, sp->name);
        }
        httpSetSoftware(EJS_HTTPSERVER_NAME);
        httpSetEndpointAsync(endpoint, sp->async);
        httpSetEndpointContext(endpoint, sp);
        httpSetEndpointNotifier(endpoint, stateChangeNotifier);

        /*
            This is only required when http is using non-ejs handlers and/or filters
         */
        documents = ejsGetProperty(ejs, sp, ES_ejs_web_HttpServer_documents);
        if (ejsIs(ejs, documents, Path)) {
            httpSetRouteDocuments(route, documents->value);
        }
#if KEEP
        //  TODO -- what to do with home?
        //  TODO - if removed, then the "home" property should be removed?
        home = ejsGetProperty(ejs, sp, ES_ejs_web_HttpServer_home);
        if (ejsIs(ejs, home, Path)) {
            httpSetRoutDir(host, home->value);
        }
#endif
        if (httpStartEndpoint(endpoint) < 0) {
            httpDestroyEndpoint(sp->endpoint);
            sp->endpoint = 0;
            ejsThrowIOError(ejs, "Cannot listen on %s", address->value);
        }
    }
    if (ejs->httpServers == 0) {
        ejs->httpServers = mprCreateList(-1, MPR_LIST_STATIC_VALUES);
    }
    /* Remove to make sure old listening() registrations are removed */
    mprRemoveItem(ejs->httpServers, sp);
    mprAddItem(ejs->httpServers, sp);
    return 0;
}
Exemple #28
0
PUBLIC EjsAny *ejsGetItem(Ejs *ejs, EjsArray *ap, int index)
{
    return ejsGetProperty(ejs, ap, index);
}
Exemple #29
0
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);
        }
    }
}
Exemple #30
0
/*
    Find a variable in an object considering namespaces. If the space is "", then search for the property name using
    the set of open namespaces.
 */
int ejsLookupVarWithNamespaces(Ejs *ejs, EjsAny *obj, EjsName name, EjsLookup *lookup)
{
    EjsNamespace    *nsp;
    EjsName         qname, target;
    EjsString       *space;
    EjsBlock        *b;
    MprList         *globalSpaces;
    int             next, slotNum;

    assert(obj);
    assert(name.name);
    assert(name.space);
    assert(lookup);

    b = (EjsBlock*) ejs->global;
    globalSpaces = &b->namespaces;

    if (name.space->value[0]) {
        /* Lookup with an explicit namespace */
        slotNum = ejsLookupProperty(ejs, obj, name);
        lookup->name = name;

    } else {
        /* 
            Lookup with the set of open namespaces in the current scope 
            Special lookup with space == NULL. Means lookup only match if there is only one property of this name 
         */
        qname.space = NULL;
        qname.name = name.name;
        if ((slotNum = ejsLookupProperty(ejs, obj, qname)) >= 0) {
            if (TYPE(obj)->virtualSlots) {
                lookup->name = name;
            } else {
                target = ejsGetPropertyName(ejs, obj, slotNum);
                lookup->name = target;
                space = name.space;
                if (space->value[0] && space != target.space) {
                    /* Unique name match. Name matches, but namespace does not */
                    slotNum = -1;
                } else if (target.space && target.space->value[0]) {
                    /* OPT - Look at global spaces first */
                    for (next = -1; (nsp = mprGetPrevItem(globalSpaces, &next)) != 0; ) {
                        if (nsp->value == target.space) {
                            goto done;
                        }
                    }
                    //  OPT -- need a fast way to know if the space is a standard reserved namespace or not */
                    /* Verify namespace is open */
                    for (b = ejs->state->bp; b; b = b->scope) {
                        //  OPT. Doing some namespaces multiple times. Fix in compiler.
                        for (next = -1; (nsp = mprGetPrevItem(&b->namespaces, &next)) != 0; ) {
                            if (nsp->value == target.space) {
                                goto done;
                            }
                        }
                    }
                    slotNum = -1;
                }
            }

        } else {
            qname = name;
            for (b = ejs->state->bp; b; b = b->scope) {
                for (next = -1; (nsp = (EjsNamespace*) mprGetPrevItem(&b->namespaces, &next)) != 0; ) {
                    qname.space = nsp->value;
                    if ((slotNum = ejsLookupProperty(ejs, obj, qname)) >= 0) {
                        lookup->name = qname;
                        goto done;
                    }
                }
            }
            for (next = -1; (nsp = mprGetPrevItem(globalSpaces, &next)) != 0; ) {
                qname.space = nsp->value;
                if ((slotNum = ejsLookupProperty(ejs, obj, qname)) >= 0) {
                    lookup->name = qname;
                    goto done;
                }
            }
        }
    }
done:
    if (slotNum >= 0) {
        //  OPT MUST GET RID OF THIS. Means that every store does a get
        lookup->ref = ejsGetProperty(ejs, obj, slotNum);
        if (ejs->exception) {
            slotNum = -1;
        } else {
            lookup->obj = obj;
            lookup->slotNum = slotNum;
            lookup->trait = ejsGetPropertyTraits(ejs, lookup->obj, lookup->slotNum);
        }
    }
    return slotNum;
}