Index: runtime/vm/unit_test.cc |
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc |
index 54352e5a350dbf8358c017a0837491d3882a39b8..c6b6bdb1b643cd4c9604e1bec773bbfa5287e09e 100644 |
--- a/runtime/vm/unit_test.cc |
+++ b/runtime/vm/unit_test.cc |
@@ -17,6 +17,7 @@ |
#include "vm/compiler.h" |
#include "vm/dart_api_impl.h" |
#include "vm/disassembler.h" |
+#include "vm/isolate_reload.h" |
#include "vm/parser.h" |
#include "vm/symbols.h" |
#include "vm/thread.h" |
@@ -66,11 +67,62 @@ Dart_Isolate TestCase::CreateIsolate(const uint8_t* buffer, const char* name) { |
static const char* kPackageScheme = "package:"; |
+ |
static bool IsPackageSchemeURL(const char* url_name) { |
static const intptr_t kPackageSchemeLen = strlen(kPackageScheme); |
return (strncmp(url_name, kPackageScheme, kPackageSchemeLen) == 0); |
} |
+ |
+static bool IsImportableTestLib(const char* url_name) { |
+ const char* kImportTestLibUri = "importable_test_lib"; |
+ static const intptr_t kImportTestLibUriLen = strlen(kImportTestLibUri); |
+ return (strncmp(url_name, kImportTestLibUri, kImportTestLibUriLen) == 0); |
+} |
+ |
+ |
+static Dart_Handle ImportableTestLibSource() { |
+ const char* kScript = |
+ "importedFunc() => 'a';\n" |
+ "importedIntFunc() => 4;\n" |
+ "class ImportedMixin {\n" |
+ " mixinFunc() => 'mixin';\n" |
+ "}\n"; |
+ return DartUtils::NewString(kScript); |
+} |
+ |
+ |
+static bool IsIsolateReloadTestLib(const char* url_name) { |
+ const char* kIsolateReloadTestLibUri = "isolate_reload_test_helper"; |
+ static const intptr_t kIsolateReloadTestLibUriLen = |
+ strlen(kIsolateReloadTestLibUri); |
+ return (strncmp(url_name, |
+ kIsolateReloadTestLibUri, |
+ kIsolateReloadTestLibUriLen) == 0); |
+} |
+ |
+ |
+#ifndef PRODUCT |
+static Dart_Handle IsolateReloadTestLibSource() { |
+ // Special library with one function. |
+ return DartUtils::NewString("void reloadTest() native 'Reload_Test';\n"); |
+} |
+ |
+ |
+static void ReloadTest(Dart_NativeArguments native_args) { |
+ DART_CHECK_VALID(TestCase::TriggerReload()); |
+} |
+ |
+ |
+static Dart_NativeFunction IsolateReloadTestNativeResolver( |
+ Dart_Handle name, |
+ int num_of_arguments, |
+ bool* auto_setup_scope) { |
+ return ReloadTest; |
+} |
+#endif // !PRODUCT |
+ |
+ |
static Dart_Handle ResolvePackageUri(const char* uri_chars) { |
const int kNumArgs = 1; |
Dart_Handle dart_args[kNumArgs]; |
@@ -81,9 +133,25 @@ static Dart_Handle ResolvePackageUri(const char* uri_chars) { |
dart_args); |
} |
+ |
+static ThreadLocalKey script_reload_key = kUnsetThreadLocalKey; |
+ |
static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, |
Dart_Handle library, |
Dart_Handle url) { |
+ if (tag == Dart_kScriptTag) { |
+ // Reload request. |
+ ASSERT(script_reload_key != kUnsetThreadLocalKey); |
+ const char* script_source = |
+ reinterpret_cast<const char*>( |
+ OSThread::GetThreadLocal(script_reload_key)); |
+ ASSERT(script_source != NULL); |
+ OSThread::SetThreadLocal(script_reload_key, NULL); |
+ return Dart_LoadScript(url, |
+ NewString(script_source), |
+ 0, |
+ 0); |
+ } |
if (!Dart_IsLibrary(library)) { |
return Dart_NewApiError("not a library"); |
} |
@@ -105,6 +173,10 @@ static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, |
bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_chars); |
bool is_io_library = DartUtils::IsDartIOLibURL(library_url_string); |
if (tag == Dart_kCanonicalizeUrl) { |
+ // Already canonicalized. |
+ if (IsImportableTestLib(url_chars) || IsIsolateReloadTestLib(url_chars)) { |
+ return url; |
+ } |
// If this is a Dart Scheme URL then it is not modified as it will be |
// handled by the VM internally. |
if (is_dart_scheme_url || is_io_library) { |
@@ -128,6 +200,17 @@ static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, |
return DartUtils::NewError("Do not know how to load '%s'", url_chars); |
} |
} |
+ if (IsImportableTestLib(url_chars)) { |
+ return Dart_LoadLibrary(url, ImportableTestLibSource(), 0, 0); |
+ } |
+ NOT_IN_PRODUCT( |
+ if (IsIsolateReloadTestLib(url_chars)) { |
+ Dart_Handle library = |
+ Dart_LoadLibrary(url, IsolateReloadTestLibSource(), 0, 0); |
+ DART_CHECK_VALID(library); |
+ Dart_SetNativeResolver(library, IsolateReloadTestNativeResolver, 0); |
+ return library; |
+ }) |
if (is_io_library) { |
ASSERT(tag == Dart_kSourceTag); |
return Dart_LoadSource(library, |
@@ -177,6 +260,61 @@ Dart_Handle TestCase::LoadTestScript(const char* script, |
} |
+#ifndef PRODUCT |
+ |
+ |
+void TestCase::SetReloadTestScript(const char* script) { |
+ if (script_reload_key == kUnsetThreadLocalKey) { |
+ script_reload_key = OSThread::CreateThreadLocal(); |
+ } |
+ ASSERT(script_reload_key != kUnsetThreadLocalKey); |
+ ASSERT(OSThread::GetThreadLocal(script_reload_key) == 0); |
+ // Store the new script in TLS. |
+ OSThread::SetThreadLocal(script_reload_key, reinterpret_cast<uword>(script)); |
+} |
+ |
+ |
+Dart_Handle TestCase::TriggerReload() { |
+ Isolate* isolate = Isolate::Current(); |
+ |
+ { |
+ TransitionNativeToVM transition(Thread::Current()); |
+ isolate->ReloadSources(/* test_mode = */ true); |
+ } |
+ |
+ return Dart_FinalizeLoading(false); |
+} |
+ |
+ |
+Dart_Handle TestCase::GetReloadErrorOrRootLibrary() { |
+ Isolate* isolate = Isolate::Current(); |
+ |
+ if (isolate->reload_context() != NULL) { |
+ // We should only have a reload context hanging around if an error occurred. |
+ ASSERT(isolate->reload_context()->has_error()); |
+ // Return a handle to the error. |
+ return Api::NewHandle(Thread::Current(), |
+ isolate->reload_context()->error()); |
+ } |
+ return Dart_RootLibrary(); |
+} |
+ |
+ |
+Dart_Handle TestCase::ReloadTestScript(const char* script) { |
+ SetReloadTestScript(script); |
+ |
+ Dart_Handle result = TriggerReload(); |
+ if (Dart_IsError(result)) { |
+ return result; |
+ } |
+ |
+ return GetReloadErrorOrRootLibrary(); |
+} |
+ |
+ |
+#endif // !PRODUCT |
+ |
+ |
Dart_Handle TestCase::LoadCoreTestScript(const char* script, |
Dart_NativeEntryResolver resolver) { |
return LoadTestScript(script, resolver, CORELIB_TEST_URI); |
@@ -219,13 +357,12 @@ void AssemblerTest::Assemble() { |
String::Handle(String::New(kDummyScript)), |
RawScript::kSourceTag)); |
script.Tokenize(String::Handle()); |
- |
+ const Library& lib = Library::Handle(Library::CoreLibrary()); |
const Class& cls = Class::ZoneHandle( |
- Class::New(function_name, |
+ Class::New(lib, |
+ function_name, |
script, |
TokenPosition::kMinSource)); |
- const Library& lib = Library::ZoneHandle(Library::New(function_name)); |
- cls.set_library(lib); |
Function& function = Function::ZoneHandle( |
Function::New(function_name, RawFunction::kRegularFunction, |
true, false, false, false, false, cls, |
@@ -254,8 +391,9 @@ CodeGenTest::CodeGenTest(const char* name) |
Symbols::New(Thread::Current(), name)); |
// Add function to a class and that class to the class dictionary so that |
// frame walking can be used. |
+ Library& lib = Library::Handle(Library::CoreLibrary()); |
const Class& cls = Class::ZoneHandle( |
- Class::New(function_name, Script::Handle(), |
+ Class::New(lib, function_name, Script::Handle(), |
TokenPosition::kMinSource)); |
function_ = Function::New( |
function_name, RawFunction::kRegularFunction, |
@@ -264,7 +402,6 @@ CodeGenTest::CodeGenTest(const char* name) |
const Array& functions = Array::Handle(Array::New(1)); |
functions.SetAt(0, function_); |
cls.SetFunctions(functions); |
- Library& lib = Library::Handle(Library::CoreLibrary()); |
lib.AddClass(cls); |
} |