/* * 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; }
/* * Cast operands as required for invokeArrayOperator */ static EjsVar *coerceArrayOperands(Ejs *ejs, EjsVar *lhs, int opcode, EjsVar *rhs) { switch (opcode) { /* * Binary operators */ case EJS_OP_ADD: return ejsInvokeOperator(ejs, arrayToString(ejs, (EjsArray*) lhs, 0, 0), opcode, rhs); case EJS_OP_AND: case EJS_OP_DIV: case EJS_OP_MUL: case EJS_OP_OR: case EJS_OP_REM: case EJS_OP_SHL: case EJS_OP_SHR: case EJS_OP_SUB: case EJS_OP_USHR: case EJS_OP_XOR: return ejsInvokeOperator(ejs, (EjsVar*) ejs->zeroValue, opcode, rhs); case EJS_OP_COMPARE_EQ: case EJS_OP_COMPARE_NE: if (ejsIsNull(rhs) || ejsIsUndefined(rhs)) { return (EjsVar*) ((opcode == EJS_OP_COMPARE_EQ) ? ejs->falseValue: ejs->trueValue); } else if (ejsIsNumber(rhs)) { return ejsInvokeOperator(ejs, (EjsVar*) ejsToNumber(ejs, lhs), opcode, rhs); } return ejsInvokeOperator(ejs, (EjsVar*) ejsToString(ejs, lhs), opcode, rhs); case EJS_OP_COMPARE_LE: case EJS_OP_COMPARE_LT: case EJS_OP_COMPARE_GE: case EJS_OP_COMPARE_GT: if (ejsIsNumber(rhs)) { return ejsInvokeOperator(ejs, (EjsVar*) ejsToNumber(ejs, lhs), opcode, rhs); } return ejsInvokeOperator(ejs, (EjsVar*) ejsToString(ejs, lhs), opcode, rhs); case EJS_OP_COMPARE_STRICTLY_NE: case EJS_OP_COMPARE_UNDEFINED: case EJS_OP_COMPARE_NOT_ZERO: case EJS_OP_COMPARE_NULL: return (EjsVar*) ejs->trueValue; case EJS_OP_COMPARE_STRICTLY_EQ: case EJS_OP_COMPARE_FALSE: case EJS_OP_COMPARE_TRUE: case EJS_OP_COMPARE_ZERO: return (EjsVar*) ejs->falseValue; /* * Unary operators */ case EJS_OP_LOGICAL_NOT: case EJS_OP_NOT: case EJS_OP_NEG: return 0; default: ejsThrowTypeError(ejs, "Opcode %d not valid for type %s", opcode, lhs->type->qname.name); return ejs->undefinedValue; } return 0; }
static EjsVar *myEjs(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) { int i; /* Write this data back to the client */ ejsWrite(ejs, "<h1>Hello World</h1><p>Args: "); mprAssert(argv); for (i = 0; i < argc; ) { if (ejsIsNumber(argv[i])) { ejsWrite(ejs, "%d", ejsGetInt(argv[i])); } else { ejsWrite(ejs, ejsGetString(argv[i])); } if (++i < argc) { ejsWrite(ejs, " "); } } ejsWrite(ejs, "</p>"); /* * Functions can return a result */ return (EjsVar*) ejsCreateString(ejs, "sunny day"); return 0; }
static EjsVar *coerceVoidOperands(Ejs *ejs, EjsVoid *lhs, int opcode, EjsVoid *rhs) { switch (opcode) { case EJS_OP_ADD: if (!ejsIsNumber(rhs)) { return ejsInvokeOperator(ejs, (EjsVar*) ejsToString(ejs, lhs), opcode, rhs); } /* Fall through */ case EJS_OP_AND: case EJS_OP_DIV: case EJS_OP_MUL: case EJS_OP_OR: case EJS_OP_REM: case EJS_OP_SHL: case EJS_OP_SHR: case EJS_OP_SUB: case EJS_OP_USHR: case EJS_OP_XOR: return ejsInvokeOperator(ejs, (EjsVar*) ejs->nanValue, opcode, rhs); /* * Comparision */ case EJS_OP_COMPARE_LE: case EJS_OP_COMPARE_LT: case EJS_OP_COMPARE_GE: case EJS_OP_COMPARE_GT: return (EjsVar*) ejs->falseValue; case EJS_OP_COMPARE_NE: case EJS_OP_COMPARE_STRICTLY_NE: if (ejsIsNull(rhs)) { return (EjsVar*) ejs->falseValue; } return (EjsVar*) ejs->trueValue; case EJS_OP_COMPARE_EQ: case EJS_OP_COMPARE_STRICTLY_EQ: if (ejsIsNull(rhs)) { return (EjsVar*) ejs->trueValue; } return (EjsVar*) ejs->falseValue; /* * Unary operators */ case EJS_OP_LOGICAL_NOT: case EJS_OP_NOT: case EJS_OP_NEG: return 0; case EJS_OP_COMPARE_UNDEFINED: case EJS_OP_COMPARE_NOT_ZERO: case EJS_OP_COMPARE_NULL: return (EjsVar*) ejs->trueValue; case EJS_OP_COMPARE_FALSE: case EJS_OP_COMPARE_TRUE: case EJS_OP_COMPARE_ZERO: return (EjsVar*) ejs->falseValue; default: ejsThrowTypeError(ejs, "Opcode %d not valid for type %s", opcode, lhs->type->qname.name); return ejs->undefinedValue; } return 0; }
/* * native static function set maximum(limit: Number): Void */ static EjsVar *setMaxMemory(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) { int maxMemory; mprAssert(argc == 1 && ejsIsNumber(argv[0])); maxMemory = ejsGetInt(argv[0]); mprSetAllocLimits(ejs, -1, maxMemory); return 0; }
/** Get a numeric representation of a variable. @return Returns a number variable or null if an exception is thrown. */ EjsNumber *ejsToNumber(Ejs *ejs, EjsVar *vp) { if (vp == 0 || ejsIsNumber(vp)) { return (EjsNumber*) vp; } if (vp->type->helpers->castVar) { return (EjsNumber*) (vp->type->helpers->castVar)(ejs, vp, ejs->numberType); } ejsThrowInternalError(ejs, "CastVar helper not defined for type \"%s\"", vp->type->qname.name); return 0; }
/* * native static function set redline(limit: Number): Void */ static EjsVar *setRedline(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) { int redline; mprAssert(argc == 1 && ejsIsNumber(argv[0])); redline = ejsGetInt(argv[0]); if (redline <= 0) { redline = INT_MAX; } mprSetAllocLimits(ejs, redline, -1); return 0; }
static EjsVar *arrayConstructor(Ejs *ejs, EjsArray *ap, int argc, EjsVar **argv) { EjsArray *args; EjsVar *arg0, **src, **dest; int size, i; mprAssert(argc == 1 && ejsIsArray(argv[0])); args = (EjsArray*) argv[0]; if (args->length == 0) { return 0; } size = 0; arg0 = getArrayProperty(ejs, args, 0); if (args->length == 1 && ejsIsNumber(arg0)) { /* * x = new Array(size); */ size = ejsGetInt(arg0); if (size > 0 && growArray(ejs, ap, size) < 0) { ejsThrowMemoryError(ejs); return 0; } } else { /* * x = new Array(element0, element1, ..., elementN): */ size = args->length; if (size > 0 && growArray(ejs, ap, size) < 0) { ejsThrowMemoryError(ejs); return 0; } src = args->data; dest = ap->data; for (i = 0; i < size; i++) { dest[i] = src[i]; } } ap->length = size; return (EjsVar*) ap; }
static bool compareArrayElement(Ejs *ejs, EjsVar *v1, EjsVar *v2) { if (v1 == v2) { return 1; } if (v1->type != v2->type) { return 0; } if (ejsIsNumber(v1)) { return ((EjsNumber*) v1)->value == ((EjsNumber*) v2)->value; } if (ejsIsString(v1)) { return strcmp(((EjsString*) v1)->value, ((EjsString*) v2)->value) == 0; } return 0; }
static EjsVar *setArrayLength(Ejs *ejs, EjsArray *ap, int argc, EjsVar **argv) { EjsVar **data, **dest; int length; mprAssert(argc == 1 && ejsIsNumber(argv[0])); mprAssert(ejsIsArray(ap)); length = (int) ((EjsNumber*) argv[0])->value; if (length < 0) { length = 0; } if (length > ap->length) { if (growArray(ejs, ap, length) < 0) { return 0; } data = ap->data; for (dest = &data[ap->length]; dest < &data[length]; dest++) { *dest = 0; } } ap->length = length; return 0; }