void ReportException(TryCatch &try_catch, bool show_line, std::string& err_msg) { HandleScope scope; if (show_line) DisplayExceptionLine(try_catch, err_msg); String::Utf8Value trace(try_catch.StackTrace()); // range errors have a trace member set to undefined if (trace.length() > 0 && !try_catch.StackTrace()->IsUndefined()) { fprintf(stderr, "%s\n", *trace); err_msg += *trace; err_msg += "\n"; } else { // this really only happens for RangeErrors, since they're the only // kind that won't have all this info in the trace, or when non-Error // objects are thrown manually. Local<Value> er = try_catch.Exception(); bool isErrorObject = er->IsObject() && !(er->ToObject()->Get(String::New("message"))->IsUndefined()) && !(er->ToObject()->Get(String::New("name"))->IsUndefined()); if (isErrorObject) { String::Utf8Value name(er->ToObject()->Get(String::New("name"))); fprintf(stderr, "%s: ", *name); err_msg += *name; err_msg += ": "; } String::Utf8Value msg(!isErrorObject ? er : er->ToObject()->Get(String::New("message"))); fprintf(stderr, "%s\n", *msg); err_msg += *msg; err_msg += "\n"; } fflush(stderr); }
Handle<Value> TiTitaniumObject::_globalInclude(void*, TiObject*, const Arguments& args) { if (args.Length() < 2) { return ThrowException(String::New(Ti::Msg::Missing_argument)); } string id = *String::Utf8Value(args[0]->ToString()); string parentFolder = *String::Utf8Value(args[1]->ToString()); // CommonJS path rules if (id.find("/") == 0) { id.replace(id.find("/"), std::string("/").length(), rootFolder); } else if (id.find("./") == 0) { id.replace(id.find("./"), std::string("./").length(), parentFolder); } else if (id.find("../") == 0) { // count ../../../ in id and strip off back of parentFolder int count = 0; size_t idx = 0; size_t pos = 0; while (true) { idx = id.find("../", pos); if (idx == std::string::npos) { break; } else { pos = idx + 3; count++; } } // strip leading ../../ off module id id = id.substr(pos); // strip paths off the parent folder idx = 0; pos = parentFolder.size(); for (int i = 0; i < count; i++) { idx = parentFolder.find_last_of("/", pos); pos = idx - 1; } if (idx == std::string::npos) { return ThrowException(String::New("Unable to find module")); } parentFolder = parentFolder.substr(0, idx + 1); id = parentFolder + id; } else { string tempId = rootFolder + id; ifstream ifs((tempId).c_str()); if (!ifs) { id = parentFolder + id; } else { id = rootFolder + id; } } string filename = id; string javascript; { ifstream ifs((filename).c_str()); if (!ifs) { Local<Value> taggedMessage = String::New((string(Ti::Msg::No_such_native_module) + " " + id).c_str()); return ThrowException(taggedMessage); } getline(ifs, javascript, string::traits_type::to_char_type(string::traits_type::eof())); ifs.close(); } // wrap the module { size_t idx = filename.find_last_of("/"); parentFolder = filename.substr(0, idx + 1); static const string preWrap = "Ti.include = function (id) { Ti.globalInclude(id, '" + parentFolder + "')};\n"; javascript = preWrap + javascript; } TryCatch tryCatch; Handle<Script> compiledScript = Script::Compile(String::New(javascript.c_str()), String::New(filename.c_str())); if (compiledScript.IsEmpty()) { DisplayExceptionLine(tryCatch); return tryCatch.ReThrow(); } Persistent<Value> result = Persistent<Value>::New(compiledScript->Run()); if (result.IsEmpty()) { return tryCatch.ReThrow(); } return Undefined(); }
Handle<Value> TiRootObject::_globalRequire(void*, TiObject*, const Arguments& args) { if (args.Length() < 2) { return ThrowException(String::New(Ti::Msg::Missing_argument)); } string id = *String::Utf8Value(args[0]->ToString()); string parentFolder = *String::Utf8Value(args[1]->ToString()); // CommonJS path rules if (id.find("/") == 0) { id.replace(id.find("/"), std::string("/").length(), rootFolder); } else if (id.find("./") == 0) { id.replace(id.find("./"), std::string("./").length(), parentFolder); } else if (id.find("../") == 0) { // count ../../../ in id and strip off back of parentFolder int count = 0; size_t idx = 0; size_t pos = 0; while (true) { idx = id.find("../", pos); if (idx == std::string::npos) { break; } else { pos = idx + 3; count++; } } // strip leading ../../ off module id id = id.substr(pos); // strip paths off the parent folder idx = 0; pos = parentFolder.size(); for (int i = 0; i < count; i++) { idx = parentFolder.find_last_of("/", pos); pos = idx - 1; } if (idx == std::string::npos) { return ThrowException(String::New("Unable to find module")); } parentFolder = parentFolder.substr(0, idx + 1); id = parentFolder + id; } else { string tempId = rootFolder + id; ifstream ifs((tempId + ".js").c_str()); if (!ifs) { id = parentFolder + id; } else { id = rootFolder + id; } } string filename = id + ".js"; // check if cached static map<string, Persistent<Value> > cache; map<string, Persistent<Value> >::const_iterator cachedValue = cache.find(id); if (cachedValue != cache.end()) { return cachedValue->second; } string javascript; { ifstream ifs((filename).c_str()); if (!ifs) { Local<Value> taggedMessage = String::New((string(Ti::Msg::No_such_native_module) + " " + id).c_str()); return ThrowException(taggedMessage); } getline(ifs, javascript, string::traits_type::to_char_type(string::traits_type::eof())); ifs.close(); } // wrap the module { size_t idx = filename.find_last_of("/"); parentFolder = filename.substr(0, idx + 1); static const string requireWithParent = "var require = function (id) { return globalRequire(id, '" + parentFolder + "')};\n"; static const string preWrap = "(function () {" + requireWithParent + "\nvar module = { exports: {} }; var exports = module.exports;\n"; static const string postWrap = "\nreturn module.exports; })();"; javascript = preWrap + javascript + postWrap; } TryCatch tryCatch; Handle<Script> compiledScript = Script::Compile(String::New(javascript.c_str()), String::New(filename.c_str())); if (compiledScript.IsEmpty()) { DisplayExceptionLine(tryCatch); return tryCatch.ReThrow(); } Persistent<Value> result = Persistent<Value>::New(compiledScript->Run()); if (result.IsEmpty()) { return tryCatch.ReThrow(); } // cache result cache.insert(pair<string, Persistent<Value> >(id, result)); return result; }