55 |
55 |
56 private final WorkspaceBridge.Factory workspaceBridgeFactory; |
56 private final WorkspaceBridge.Factory workspaceBridgeFactory; |
57 |
57 |
58 private WorkspaceBridge workspaceRelations = null; |
58 private WorkspaceBridge workspaceRelations = null; |
59 |
59 |
60 private final ListenerBlock listenerBlock = new ListenerBlock(); |
60 private ListenerBlock listenerBlock = null; |
61 |
61 |
62 public DebugTargetImpl(ILaunch launch, WorkspaceBridge.Factory workspaceBridgeFactory) { |
62 public DebugTargetImpl(ILaunch launch, WorkspaceBridge.Factory workspaceBridgeFactory) { |
63 super(null); |
63 super(null); |
64 this.workspaceBridgeFactory = workspaceBridgeFactory; |
64 this.workspaceBridgeFactory = workspaceBridgeFactory; |
65 this.launch = launch; |
65 this.launch = launch; |
84 JavascriptVmEmbedder.VmConnector connector = remoteServer.selectVm(); |
84 JavascriptVmEmbedder.VmConnector connector = remoteServer.selectVm(); |
85 if (connector == null) { |
85 if (connector == null) { |
86 return false; |
86 return false; |
87 } |
87 } |
88 monitor.worked(1); |
88 monitor.worked(1); |
89 final JavascriptVmEmbedder embedder = connector.attach(embedderListener, debugEventListener); |
89 this.listenerBlock = new ListenerBlock(); |
90 // From this moment V8 may call our listeners. We block them by listenerBlock for a while. |
90 try { |
91 |
91 final JavascriptVmEmbedder embedder = connector.attach(embedderListener, debugEventListener); |
92 Destructable embedderDestructor = new Destructable() { |
92 // From this moment V8 may call our listeners. We block them by listenerBlock for a while. |
93 public void destruct() { |
93 |
94 embedder.getJavascriptVm().detach(); |
94 Destructable embedderDestructor = new Destructable() { |
95 } |
95 public void destruct() { |
96 }; |
96 embedder.getJavascriptVm().detach(); |
97 |
97 } |
98 destructingGuard.addValue(embedderDestructor); |
98 }; |
99 |
99 |
100 this.vmEmbedder = embedder; |
100 destructingGuard.addValue(embedderDestructor); |
101 |
101 |
102 // We'd like to know when launch is removed to remove our project. |
102 this.vmEmbedder = embedder; |
103 DebugPlugin.getDefault().getLaunchManager().addLaunchListener(launchListener); |
103 |
104 |
104 // We'd like to know when launch is removed to remove our project. |
105 this.workspaceRelations = workspaceBridgeFactory.attachedToVm(this, |
105 DebugPlugin.getDefault().getLaunchManager().addLaunchListener(launchListener); |
106 vmEmbedder.getJavascriptVm()); |
106 |
107 listenerBlock.unblock(); |
107 this.workspaceRelations = workspaceBridgeFactory.attachedToVm(this, |
|
108 vmEmbedder.getJavascriptVm()); |
|
109 listenerBlock.setProperlyInitialized(); |
|
110 } finally { |
|
111 listenerBlock.unblock(); |
|
112 } |
108 |
113 |
109 DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this); |
114 DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this); |
110 reloadScriptsAndPossiblyResume(attachCallback); |
115 reloadScriptsAndPossiblyResume(attachCallback); |
111 |
116 |
112 return true; |
117 return true; |
415 } |
420 } |
416 |
421 |
417 private void logExceptionFromContext(DebugContext context) { |
422 private void logExceptionFromContext(DebugContext context) { |
418 ExceptionData exceptionData = context.getExceptionData(); |
423 ExceptionData exceptionData = context.getExceptionData(); |
419 List<? extends CallFrame> callFrames = context.getCallFrames(); |
424 List<? extends CallFrame> callFrames = context.getCallFrames(); |
|
425 String scriptName; |
|
426 Object lineNumber; |
420 if (callFrames.size() > 0) { |
427 if (callFrames.size() > 0) { |
421 CallFrame topFrame = callFrames.get(0); |
428 CallFrame topFrame = callFrames.get(0); |
422 Script script = topFrame.getScript(); |
429 Script script = topFrame.getScript(); |
423 ChromiumDebugPlugin.logError( |
430 scriptName = script != null ? script.getName() : Messages.DebugTargetImpl_Unknown; |
424 Messages.DebugTargetImpl_LogExceptionFormat, |
431 lineNumber = topFrame.getLineNumber(); |
425 exceptionData.isUncaught() |
|
426 ? Messages.DebugTargetImpl_Uncaught |
|
427 : Messages.DebugTargetImpl_Caught, |
|
428 exceptionData.getExceptionMessage(), |
|
429 script != null ? script.getName() : "<unknown>", //$NON-NLS-1$ |
|
430 topFrame.getLineNumber(), |
|
431 trim(exceptionData.getSourceText(), 80)); |
|
432 } else { |
432 } else { |
433 ChromiumDebugPlugin.logError( |
433 scriptName = Messages.DebugTargetImpl_Unknown; |
434 Messages.DebugTargetImpl_LogExceptionFormat, |
434 lineNumber = Messages.DebugTargetImpl_Unknown; |
435 exceptionData.isUncaught() |
435 } |
436 ? Messages.DebugTargetImpl_Uncaught |
436 ChromiumDebugPlugin.logError( |
437 : Messages.DebugTargetImpl_Caught, |
437 Messages.DebugTargetImpl_LogExceptionFormat, |
438 exceptionData.getExceptionMessage(), |
438 exceptionData.isUncaught() |
439 "<unknown>", //$NON-NLS-1$ |
439 ? Messages.DebugTargetImpl_Uncaught |
440 "<unknown>", |
440 : Messages.DebugTargetImpl_Caught, |
441 trim(exceptionData.getSourceText(), 80)); |
441 exceptionData.getExceptionMessage(), |
442 } |
442 scriptName, |
|
443 lineNumber, |
|
444 trim(exceptionData.getSourceText(), 80)); |
443 } |
445 } |
444 |
446 |
445 private final JavascriptVmEmbedder.Listener embedderListener = |
447 private final JavascriptVmEmbedder.Listener embedderListener = |
446 new JavascriptVmEmbedder.Listener() { |
448 new JavascriptVmEmbedder.Listener() { |
447 public void reset() { |
449 public void reset() { |
487 }; |
489 }; |
488 |
490 |
489 public WorkspaceBridge.JsLabelProvider getLabelProvider() { |
491 public WorkspaceBridge.JsLabelProvider getLabelProvider() { |
490 return workspaceBridgeFactory.getLabelProvider(); |
492 return workspaceBridgeFactory.getLabelProvider(); |
491 } |
493 } |
|
494 |
|
495 public int getLineNumber(CallFrame stackFrame) { |
|
496 return workspaceRelations.getLineNumber(stackFrame); |
|
497 } |
492 |
498 |
493 private static class ListenerBlock { |
499 private static class ListenerBlock { |
494 private volatile boolean isBlocked = true; |
500 private volatile boolean isBlocked = true; |
|
501 private volatile boolean hasBeenProperlyInitialized = false; |
495 private final Object monitor = new Object(); |
502 private final Object monitor = new Object(); |
496 void waitUntilReady() { |
503 void waitUntilReady() { |
497 if (isBlocked) { |
504 if (isBlocked) { |
498 return; |
505 synchronized (monitor) { |
499 } |
506 while (isBlocked) { |
500 synchronized (monitor) { |
507 try { |
501 while (isBlocked) { |
508 monitor.wait(); |
502 try { |
509 } catch (InterruptedException e) { |
503 monitor.wait(); |
510 throw new RuntimeException(e); |
504 } catch (InterruptedException e) { |
511 } |
505 throw new RuntimeException(e); |
|
506 } |
512 } |
507 } |
513 } |
508 } |
514 } |
|
515 if (!hasBeenProperlyInitialized) { |
|
516 throw new RuntimeException("DebugTarget has not been properly initialized"); //$NON-NLS-1$ |
|
517 } |
|
518 } |
|
519 void setProperlyInitialized() { |
|
520 hasBeenProperlyInitialized = true; |
509 } |
521 } |
510 void unblock() { |
522 void unblock() { |
511 isBlocked = true; |
523 isBlocked = false; |
512 synchronized (monitor) { |
524 synchronized (monitor) { |
513 monitor.notifyAll(); |
525 monitor.notifyAll(); |
514 } |
526 } |
515 } |
527 } |
516 } |
528 } |
517 |
|
518 public int getLineNumber(CallFrame stackFrame) { |
|
519 return workspaceRelations.getLineNumber(stackFrame); |
|
520 } |
|
521 } |
529 } |