Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TIMOB-9874: BlackBerry: implement require() #96

Merged
merged 4 commits into from
Jul 12, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion apidoc/Global/Global.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ methods:
require ('/myModule/module.js')

#### BlackBerry
NYI

Currently, only base paths are valid. Relative paths are NYI.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you created a JIRA task to track that NYI stuff? I can't see it from the commit description.

returns:
summary: Exported `exports` object of the required module.
type: Object
Expand Down
2 changes: 1 addition & 1 deletion blackberry/tibb/NativeLoggerWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ using namespace std;

void NativeLoggerWorker::log(const QString& t)
{
fprintf(stderr, "%s\n", t.toStdString().c_str());
fprintf(stderr, "%s", (t + "\n").toStdString().c_str());
}
1 change: 1 addition & 0 deletions blackberry/tibb/TiMessageStrings.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ TIMESSAGESTRINGS_CONST_DEF(char*, Include_file_not_found, "Include file not foun
TIMESSAGESTRINGS_CONST_DEF(char*, INTERNAL__Global_String_symbol_is_not_an_object, "INTERNAL: Global String symbol is not an object");
TIMESSAGESTRINGS_CONST_DEF(char*, INTERNAL__args0_is_not_a_number, "args[0] is not a number.");
TIMESSAGESTRINGS_CONST_DEF(char*, Missing_argument, "Missing argument");
TIMESSAGESTRINGS_CONST_DEF(char*, No_such_native_module, "No such native module");
TIMESSAGESTRINGS_CONST_DEF(char*, Numbered_argument_exceeds_the_length_of_provided_arguments, "Numbered argument exceeds the length of provided arguments");
TIMESSAGESTRINGS_CONST_DEF(char*, Too_many_arguments, "Too many arguments");

Expand Down
115 changes: 105 additions & 10 deletions blackberry/tibb/TiRootObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#include "TiMessageStrings.h"
#include "TiTitaniumObject.h"
#include "TiV8EventContainerFactory.h"

#include <fstream>
#include <sstream>

#include <QString>
#include <QUrl>
Expand Down Expand Up @@ -101,9 +103,10 @@ int TiRootObject::executeScript(NativeObjectFactory* objectFactory, const char*
Context::Scope context_scope(context_);
initializeTiObject(NULL);

const char* bootstrapFilename = "bootstrap.js";
string bootstrapJavascript;
{
ifstream ifs("app/native/framework/bootstrap.js");
ifstream ifs((string("app/native/framework/") + bootstrapFilename).c_str());
if (!ifs)
{
TiLogger::getInstance().log(Ti::Msg::ERROR__Cannot_load_bootstrap_js);
Expand All @@ -114,7 +117,7 @@ int TiRootObject::executeScript(NativeObjectFactory* objectFactory, const char*
}

TryCatch tryCatch;
Handle<Script> compiledBootstrapScript = Script::Compile(String::New(bootstrapJavascript.c_str()));
Handle<Script> compiledBootstrapScript = Script::Compile(String::New(bootstrapJavascript.c_str()), String::New(bootstrapFilename));
if (compiledBootstrapScript.IsEmpty())
{
String::Utf8Value error(tryCatch.Exception());
Expand All @@ -124,12 +127,26 @@ int TiRootObject::executeScript(NativeObjectFactory* objectFactory, const char*
Handle<Value> bootstrapResult = compiledBootstrapScript->Run();
if (bootstrapResult.IsEmpty())
{
String::Utf8Value error(tryCatch.Exception());
TiLogger::getInstance().log(*error);
Local<Value> exception = tryCatch.Exception();
// FIXME: need a way to prevent double "filename + line" output
Handle<Message> msg = tryCatch.Message();
stringstream ss;
ss << bootstrapFilename << " line ";
if (msg.IsEmpty())
{
ss << "?";
}
else
{
ss << msg->GetLineNumber();
}
ss << ": " << *String::Utf8Value(exception);
TiLogger::getInstance().log(ss.str());
return -1;
}

Handle<Script> compiledScript = Script::Compile(String::New(javaScript));
const char* filename = "app.js";
Handle<Script> compiledScript = Script::Compile(String::New(javaScript), String::New(filename));
if (compiledScript.IsEmpty())
{
String::Utf8Value error(tryCatch.Exception());
Expand All @@ -139,8 +156,21 @@ int TiRootObject::executeScript(NativeObjectFactory* objectFactory, const char*
Handle<Value> result = compiledScript->Run();
if (result.IsEmpty())
{
String::Utf8Value error(tryCatch.Exception());
TiLogger::getInstance().log(*error);
Local<Value> exception = tryCatch.Exception();
// FIXME: need a way to prevent double "filename + line" output
Handle<Message> msg = tryCatch.Message();
stringstream ss;
ss << filename << " line ";
if (msg.IsEmpty())
{
ss << "?";
}
else
{
ss << msg->GetLineNumber();
}
ss << ": " << *String::Utf8Value(exception);
TiLogger::getInstance().log(ss.str());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RootObject::executeScript function is too big, could we separate it into smaller logical pieces

return -1;
}
onStartMessagePump();
Expand Down Expand Up @@ -195,9 +225,74 @@ Handle<Value> TiRootObject::_clearTimeout(void*, TiObject*, const Arguments& arg

Handle<Value> TiRootObject::_require(void*, TiObject*, const Arguments& args)
{
// TODO: finish this
(void)args;
return Undefined();
if (args.Length() < 1)
{
return ThrowException(String::New(Ti::Msg::Missing_argument));
}

Handle<String> v8Id = args[0]->ToString();
string id = *String::Utf8Value(v8Id);

// 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 filename = id + ".js";
// TODO: need to make this relative and support com.example.module
static const string baseFolder = "app/native/assets/";
string javascript;
{
ifstream ifs((baseFolder + filename).c_str());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not handle the cases when module should load relative to current. So, for example having ui/module1 ui/module2. In app.js having require('ui/module1') in module1 having require('module2').

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a TODO for that above

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
{
static const string preWrap = "(function () { var exports = {};\n";
static const string postWrap = "\nreturn exports; })();";
javascript = preWrap + javascript + postWrap;
}

// TODO: set the correct context

TryCatch tryCatch;
Handle<Script> compiledScript = Script::Compile(String::New(javascript.c_str()), String::New(filename.c_str()));
if (compiledScript.IsEmpty())
{
return ThrowException(tryCatch.Exception());
}
Persistent<Value> result = (Persistent<Value>)compiledScript->Run();
if (result.IsEmpty())
{
Handle<Message> msg = tryCatch.Message();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should handle the case when message is empty.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

stringstream ss;
ss << filename << " line ";
if (msg.IsEmpty())
{
ss << "?";
}
else
{
ss << msg->GetLineNumber() - 1; // -1 for the wrapper
}
ss << ": " << *String::Utf8Value(tryCatch.Exception());
return ThrowException(String::New(ss.str().c_str()));
}

// cache result
cache.insert(pair<string, Persistent<Value> >(id, result));

return result;
}

Handle<Value> TiRootObject::_setInterval(void*, TiObject*, const Arguments& args)
Expand Down
20 changes: 16 additions & 4 deletions blackberry/tibb/TiTitaniumObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ bool TiTitaniumObject::canAddMembers() const
return false;
}

Handle<Value> TiTitaniumObject::_include(void* userContext, TiObject* caller, const Arguments& args)
Handle<Value> TiTitaniumObject::_include(void*, TiObject*, const Arguments& args)
{
if (args.Length() < 1)
{
Expand Down Expand Up @@ -81,7 +81,7 @@ Handle<Value> TiTitaniumObject::_include(void* userContext, TiObject* caller, co

if (!ifs)
{
return ThrowException(String::Concat(String::New(fullPath.c_str()), String::New(Ti::Msg::Include_file_not_found)));
return ThrowException(String::Concat(String::New((fullPath + " ").c_str()), String::New(Ti::Msg::Include_file_not_found)));
}

string buffer;
Expand All @@ -94,10 +94,22 @@ Handle<Value> TiTitaniumObject::_include(void* userContext, TiObject* caller, co
{
return ThrowException(tryCatch.Exception());
}
Handle<Value>result = compiledScript->Run();
Handle<Value> result = compiledScript->Run();
if (result.IsEmpty())
{
return ThrowException(tryCatch.Exception());
Handle<Message> msg = tryCatch.Message();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should handle the case when message is empty.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

stringstream ss;
ss << filename << " line ";
if (msg.IsEmpty())
{
ss << "?";
}
else
{
ss << msg->GetLineNumber();
}
ss << ": " << *String::Utf8Value(tryCatch.Exception());
return ThrowException(String::New(ss.str().c_str()));
}

// Reset relative path
Expand Down