Index: runtime/vm/service.cc |
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc |
index 2225aa41fb1f5f2d5d250a65a87bda15f0dccc5c..804c93ae3f376e874a25f76f526aed9075731272 100644 |
--- a/runtime/vm/service.cc |
+++ b/runtime/vm/service.cc |
@@ -1453,14 +1453,21 @@ static RawObject* LookupHeapObjectLibraries(Isolate* isolate, |
return lib.raw(); |
} |
if (strcmp(parts[2], "scripts") == 0) { |
- // Script ids look like "libraries/35/scripts/library%2Furl.dart" |
- if (num_parts != 4) { |
+ // Script ids look like "libraries/35/scripts/library%2Furl.dart/12345" |
+ if (num_parts != 5) { |
return Object::sentinel().raw(); |
} |
const String& id = String::Handle(String::New(parts[3])); |
ASSERT(!id.IsNull()); |
// The id is the url of the script % encoded, decode it. |
const String& requested_url = String::Handle(String::DecodeIRI(id)); |
+ |
+ // Each script id is tagged with a load time. |
+ int64_t timestamp; |
+ if (!GetInteger64Id(parts[4], ×tamp, 16) || (timestamp < 0)) { |
+ return Object::sentinel().raw(); |
+ } |
+ |
Script& script = Script::Handle(); |
String& script_url = String::Handle(); |
const Array& loaded_scripts = Array::Handle(lib.LoadedScripts()); |
@@ -1470,7 +1477,8 @@ static RawObject* LookupHeapObjectLibraries(Isolate* isolate, |
script ^= loaded_scripts.At(i); |
ASSERT(!script.IsNull()); |
script_url ^= script.url(); |
- if (script_url.Equals(requested_url)) { |
+ if (script_url.Equals(requested_url) && |
+ (timestamp == script.load_timestamp())) { |
return script.raw(); |
} |
} |
@@ -2376,6 +2384,52 @@ static bool GetSourceReport(Thread* thread, JSONStream* js) { |
} |
+static const MethodParameter* reload_sources_params[] = { |
+ RUNNABLE_ISOLATE_PARAMETER, |
+ NULL, |
+}; |
+ |
+ |
+static bool ReloadSources(Thread* thread, JSONStream* js) { |
+ Isolate* isolate = thread->isolate(); |
+ if (!isolate->compilation_allowed()) { |
+ js->PrintError(kFeatureDisabled, |
+ "Cannot reload source when running a precompiled program."); |
+ return true; |
+ } |
+ if (Dart::snapshot_kind() == Snapshot::kAppWithJIT) { |
+ js->PrintError(kFeatureDisabled, |
+ "Cannot reload source when running an app snapshot."); |
+ return true; |
+ } |
+ Dart_LibraryTagHandler handler = isolate->library_tag_handler(); |
+ if (handler == NULL) { |
+ js->PrintError(kFeatureDisabled, |
+ "A library tag handler must be installed."); |
+ return true; |
+ } |
+ if (isolate->IsReloading()) { |
+ js->PrintError(kIsolateIsReloading, |
+ "This isolate is being reloaded."); |
+ return true; |
+ } |
+ DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); |
+ ASSERT(isolate->CanReload()); |
+ |
+ if (stack->Length() > 0) { |
+ // TODO(turnidge): We need to support this case. |
+ js->PrintError(kFeatureDisabled, |
+ "Source can only be reloaded when stack is empty."); |
+ return true; |
+ } else { |
+ isolate->ReloadSources(); |
+ } |
+ |
+ PrintSuccess(js); |
+ return true; |
+} |
+ |
+ |
static bool AddBreakpointCommon(Thread* thread, |
JSONStream* js, |
const String& script_uri) { |
@@ -3950,6 +4004,8 @@ static const ServiceMethodDescriptor service_methods_[] = { |
remove_breakpoint_params }, |
{ "_restartVM", RestartVM, |
restart_vm_params }, |
+ { "_reloadSources", ReloadSources, |
+ reload_sources_params }, |
{ "resume", Resume, |
resume_params }, |
{ "_requestHeapSnapshot", RequestHeapSnapshot, |