void ejsConfigureDbTypes(Ejs *ejs) { EjsType *type; EjsName qname; ejsName(&qname, "ejs.db", "Database"); type = (EjsType*) ejsGetPropertyByName(ejs, ejs->global, &qname); if (type == 0 || !ejsIsType(type)) { ejs->hasError = 1; return; } type->instanceSize = sizeof(EjsDb); type->helpers->finalizeVar = (EjsFinalizeVarHelper) finalizeDb; ejsBindMethod(ejs, type, ES_ejs_db_Database_Database, (EjsNativeFunction) dbConstructor); ejsBindMethod(ejs, type, ES_ejs_db_Database_close, (EjsNativeFunction) closeDb); ejsBindMethod(ejs, type, ES_ejs_db_Database_sql, (EjsNativeFunction) sql); #if UNUSED ejsSetAccessors(ejs, type, ES_ejs_db_Database_tables, (EjsNativeFunction) tables, -1, 0); ejsBindMethod(ejs, type, ES_ejs_db_Database_start, startDb); ejsBindMethod(ejs, type, ES_ejs_db_Database_commit, commitDb); ejsBindMethod(ejs, type, ES_ejs_db_Database_rollback, rollbackDb); #endif }
/* * Format the stack backtrace */ char *ejsFormatStack(Ejs *ejs) { EjsFrame *frame; EjsType *type; EjsFunction *fun; cchar *typeName, *functionName, *line, *typeSep, *codeSep; char *backtrace, *traceLine; int level, len; mprAssert(ejs); backtrace = 0; len = 0; level = 0; for (frame = ejs->frame; frame; frame = frame->caller) { if (frame->currentLine == 0) { line = ""; } else { for (line = frame->currentLine; *line && isspace((int) *line); line++) { ; } } typeName = ""; functionName = "global"; fun = &frame->function; if (fun) { if (fun->owner) { functionName = ejsGetPropertyName(ejs, fun->owner, fun->slotNum).name; } if (ejsIsType(fun->owner)) { type = (EjsType*) fun->owner; if (type) { typeName = type->qname.name; } } } typeSep = (*typeName) ? "." : ""; codeSep = (*line) ? "->" : ""; if (mprAllocSprintf(ejs, &traceLine, MPR_MAX_STRING, " [%02d] %s, %s%s%s, line %d %s %s\n", level++, frame->fileName ? frame->fileName : "script", typeName, typeSep, functionName, frame->lineNumber, codeSep, line) < 0) { break; } backtrace = (char*) mprRealloc(ejs, backtrace, len + (int) strlen(traceLine) + 1); if (backtrace == 0) { return 0; } memcpy(&backtrace[len], traceLine, strlen(traceLine) + 1); len += (int) strlen(traceLine); mprFree(traceLine); } return backtrace; }
static EjsString *getBlockName(EjsMod *mp, EjsObj *block, int slotNum) { EjsName qname; if (block) { if (ejsIsType(mp->ejs, block)) { return ((EjsType*) block)->qname.name; } else if (ejsIsFunction(mp->ejs, block)) { return ((EjsFunction*) block)->name; } } qname = ejsGetPropertyName(mp->ejs, block, slotNum); return qname.name; }
/* Find a property in an object or its prototype and base classes. */ int ejsLookupVar(Ejs *ejs, EjsAny *obj, EjsName name, EjsLookup *lookup) { EjsType *type; EjsPot *prototype; int slotNum, nthBase; assert(obj); assert(lookup); memset(lookup, 0, sizeof(*lookup)); /* Lookup simple object */ if ((slotNum = ejsLookupVarWithNamespaces(ejs, obj, name, lookup)) >= 0) { return slotNum; } /* Lookup prototype chain */ for (nthBase = 1, type = TYPE(obj); type; type = type->baseType, nthBase++) { if ((prototype = type->prototype) == 0 || prototype->shortScope) { break; } if ((slotNum = ejsLookupVarWithNamespaces(ejs, prototype, name, lookup)) >= 0) { lookup->nthBase = nthBase; return slotNum; } } /* Lookup base-class chain */ type = ejsIsType(ejs, obj) ? ((EjsType*) obj)->baseType : TYPE(obj); for (nthBase = 1; type; type = type->baseType, nthBase++) { if (type->constructor.block.pot.shortScope) { continue; } if ((slotNum = ejsLookupVarWithNamespaces(ejs, type, name, lookup)) >= 0) { lookup->nthBase = nthBase; return slotNum; } } return -1; }
/* Look for a variable by name in the scope chain and return the location in "lookup" and a positive slot number if found. If the name.space is non-empty, then only the given namespace will be used. Otherwise the set of open namespaces will be used. The lookup structure will contain details about the location of the variable. */ static int lookupVarInBlock(Ejs *ejs, EjsBlock *bp, EjsName name, EjsLookup *lookup) { EjsFrame *frame; EjsState *state; EjsType *type; EjsObj *thisObj; EjsPot *prototype; int slotNum, nthBase; assert(ejs); assert(name.name); assert(name.space); assert(lookup); state = ejs->state; slotNum = -1; thisObj = state->fp->function.boundThis; /* Search simple block */ lookup->originalObj = bp; if ((slotNum = ejsLookupVarWithNamespaces(ejs, bp, name, lookup)) >= 0) { return slotNum; } /* Optimized lookup for frames and types. Simple blocks don't need prototype lookup - so examine the type of block */ if (ejsIsFrame(ejs, bp)) { frame = (EjsFrame*) bp; if (thisObj && frame->function.boundThis == thisObj && thisObj != ejs->global && !frame->function.staticMethod && !frame->function.isInitializer) { lookup->originalObj = thisObj; /* Instance method only */ if ((slotNum = ejsLookupVarWithNamespaces(ejs, thisObj, name, lookup)) >= 0) { return slotNum; } /* Search prototype chain */ for (nthBase = 1, type = TYPE(thisObj); type; type = type->baseType, nthBase++) { if ((prototype = type->prototype) == 0 || prototype->shortScope) { break; } if ((slotNum = ejsLookupVarWithNamespaces(ejs, prototype, name, lookup)) >= 0) { lookup->nthBase = nthBase; lookup->type = type; return slotNum; } } if (frame->function.isConstructor) { for (nthBase = 1, type = (EjsType*) TYPE(thisObj); type; type = type->baseType, nthBase++) { if (type->constructor.block.pot.shortScope) { break; } if ((slotNum = ejsLookupVarWithNamespaces(ejs, type, name, lookup)) >= 0) { lookup->nthBase = nthBase; return slotNum; } } } thisObj = 0; } } else if (ejsIsType(ejs, bp)) { /* Search base class chain */ // OPT -- remove nthBase. Not needed if not binding. for (nthBase = 1, type = (EjsType*) bp; type; type = type->baseType, nthBase++) { if (type->constructor.block.pot.shortScope) { break; } if ((slotNum = ejsLookupVarWithNamespaces(ejs, type, name, lookup)) >= 0) { lookup->nthBase = nthBase; return slotNum; } } } return -1; }
/* * Format the stack backtrace */ char *ejsFormatStack(Ejs *ejs, EjsError *error) { EjsType *type; EjsFrame *fp; cchar *typeName, *functionName, *line, *typeSep, *codeSep; char *backtrace, *traceLine; int level, len, oldFlags; mprAssert(ejs); backtrace = 0; len = 0; level = 0; /* * Pretend to be the compiler so we can access function frame names */ oldFlags = ejs->flags; ejs->flags |= EJS_FLAG_COMPILER; for (fp = ejs->state->fp; fp; fp = fp->caller) { typeName = ""; functionName = "global"; if (fp->currentLine == 0) { line = ""; } else { for (line = fp->currentLine; *line && isspace((int) *line); line++) { ; } } if (fp) { if (fp->function.owner && fp->function.slotNum >= 0) { functionName = ejsGetPropertyName(ejs, fp->function.owner, fp->function.slotNum).name; } if (ejsIsType(fp->function.owner)) { type = (EjsType*) fp->function.owner; if (type) { typeName = type->qname.name; } } } typeSep = (*typeName) ? "." : ""; codeSep = (*line) ? "->" : ""; if (error && backtrace == 0) { error->filename = mprStrdup(error, fp->filename); error->lineNumber = fp->lineNumber; } if ((traceLine = mprAsprintf(ejs, MPR_MAX_STRING, " [%02d] %s, %s%s%s, line %d %s %s\n", level++, fp->filename ? fp->filename : "script", typeName, typeSep, functionName, fp->lineNumber, codeSep, line)) == NULL) { break; } backtrace = (char*) mprRealloc(ejs, backtrace, len + (int) strlen(traceLine) + 1); if (backtrace == 0) { return 0; } memcpy(&backtrace[len], traceLine, strlen(traceLine) + 1); len += (int) strlen(traceLine); mprFree(traceLine); } ejs->flags = oldFlags; if (error) { error->stack = backtrace; } return backtrace; }
/* List the various property slot assignments */ static void lstSlotAssignments(EjsMod *mp, EjsModule *module, EjsObj *parent, int slotNum, EjsObj *obj) { Ejs *ejs; EjsTrait *trait; EjsType *type; EjsObj *vp; EjsPot *prototype; EjsFunction *fun; EjsBlock *block; EjsName qname; int i, numInherited, count; mprAssert(obj); mprAssert(module); ejs = mp->ejs; if (VISITED(obj)) { return; } SET_VISITED(obj, 1); if (obj == ejs->global) { mprFprintf(mp->file, "\n#\n" "# Global slot assignments (Num prop %d)\n" "#\n", ejsGetLength(ejs, obj)); /* List slots for global */ for (i = module->firstGlobal; i < module->lastGlobal; i++) { trait = ejsGetPropertyTraits(ejs, ejs->global, i); qname = ejsGetPropertyName(ejs, ejs->global, i); if (qname.name == 0) { continue; } lstVarSlot(mp, module, &qname, trait, i); } /* List slots for the initializer */ fun = (EjsFunction*) module->initializer; if (fun) { mprFprintf(mp->file, "\n#\n" "# Initializer slot assignments (Num prop %d)\n" "#\n", ejsGetLength(ejs, (EjsObj*) fun)); count = ejsGetLength(ejs, (EjsObj*) fun); for (i = 0; i < count; i++) { trait = ejsGetPropertyTraits(ejs, (EjsObj*) fun, i); qname = ejsGetPropertyName(ejs, (EjsObj*) fun, i); if (qname.name == 0) { continue; } mprAssert(trait); lstVarSlot(mp, module, &qname, trait, i); } } } else if (ejsIsFunction(ejs, obj)) { fun = (EjsFunction*) obj; count = ejsGetLength(ejs, (EjsObj*) obj); if (count > 0) { mprFprintf(mp->file, "\n#\n" "# Local slot assignments for the \"%@\" function (Num slots %d)\n" "#\n", fun->name, count); for (i = 0; i < count; i++) { trait = ejsGetPropertyTraits(ejs, obj, i); mprAssert(trait); qname = ejsGetPropertyName(ejs, obj, i); lstVarSlot(mp, module, &qname, trait, i); } } } else if (ejsIsType(ejs, obj)) { /* Types */ type = (EjsType*) obj; mprFprintf(mp->file, "\n#\n" "# Class slot assignments for the \"%@\" class (Num slots %d)\n" "#\n", type->qname.name, ejsGetLength(ejs, (EjsObj*) type)); count = ejsGetLength(ejs, (EjsObj*) type); for (i = 0; i < count; i++) { trait = ejsGetPropertyTraits(ejs, (EjsObj*) type, i); mprAssert(trait); qname = ejsGetPropertyName(ejs, obj, i); lstVarSlot(mp, module, &qname, trait, i); } prototype = type->prototype; if (type->baseType && type->baseType->prototype) { numInherited = ejsGetLength(ejs, type->baseType->prototype); } else { numInherited = 0; } mprFprintf(mp->file, "\n#\n" "# Instance slot assignments for the \"%@\" class (Num prop %d, num inherited %d)\n" "#\n", type->qname.name, prototype ? ejsGetLength(ejs, prototype): 0, numInherited); if (prototype) { count = ejsGetLength(ejs, prototype); for (i = 0; i < count; i++) { trait = ejsGetPropertyTraits(ejs, prototype, i); mprAssert(trait); qname = ejsGetPropertyName(ejs, prototype, i); if (qname.name) { lstVarSlot(mp, module, &qname, trait, i); } } } } else if (ejsIsBlock(ejs, obj)) { qname = ejsGetPropertyName(ejs, parent, slotNum); block = (EjsBlock*) obj; count = ejsGetLength(ejs, (EjsObj*) block); if (count > 0) { mprFprintf(mp->file, "\n#\n" "# Block slot assignments for the \"%@\" (Num slots %d)\n" "#\n", qname.name, ejsGetLength(ejs, obj)); count = ejsGetLength(ejs, obj); for (i = 0; i < count; i++) { trait = ejsGetPropertyTraits(ejs, obj, i); mprAssert(trait); qname = ejsGetPropertyName(ejs, obj, i); lstVarSlot(mp, module, &qname, trait, i); } } } /* Now recurse on types, functions and blocks */ if (obj == ejs->global) { i = module->firstGlobal; count = module->lastGlobal; } else { i = 0; count = ejsGetLength(ejs, obj); } for (; i < count; i++) { qname = ejsGetPropertyName(ejs, obj, i); vp = ejsGetProperty(ejs, obj, i); if (vp == 0) { continue; } if (ejsIsType(ejs, vp) || ejsIsFunction(ejs, vp) || ejsIsBlock(ejs, vp)) { lstSlotAssignments(mp, module, obj, i, vp); } } SET_VISITED(obj, 0); }
/* Return the length of bytes added to buf */ static void getGlobal(EjsMod *mp, char *buf, int buflen) { Ejs *ejs; EjsName qname; EjsObj *vp; int t, slotNum; ejs = mp->ejs; vp = 0; if ((t = (int) getNum(mp)) < 0) { mprSprintf(buf, buflen, "<can't read code>"); return; } switch (t & EJS_ENCODE_GLOBAL_MASK) { default: mprAssert(0); return; case EJS_ENCODE_GLOBAL_NOREF: return; case EJS_ENCODE_GLOBAL_SLOT: /* Type is a builtin primitive type or we are binding globals. */ slotNum = t >> 2; if (0 <= slotNum && slotNum < ejsGetLength(ejs, ejs->global)) { vp = ejsGetProperty(ejs, ejs->global, slotNum); } if (vp && ejsIsType(ejs, vp)) { mprSprintf(buf, buflen, "<type: 0x%x, %N> ", t, ((EjsType*) vp)->qname); } break; case EJS_ENCODE_GLOBAL_NAME: /* Type was unknown at compile time */ qname.name = ejsCreateStringFromConst(ejs, mp->module, t >> 2); if (qname.name == 0) { mprAssert(0); mprSprintf(buf, buflen, "<var: 0x%x, missing name> ", t); return; } if ((qname.space = getString(mp->ejs, mp)) == 0) { mprSprintf(buf, buflen, "<var: 0x%x, missing namespace> ", t); return; } if (qname.name) { vp = ejsGetPropertyByName(ejs, ejs->global, qname); } mprSprintf(buf, buflen, "<var: 0x%x, %N> ", t, qname); break; } if (vp == 0) { mprSprintf(buf, buflen, "<var: %d, cannot resolve var/typ at slot e> ", t); } }