Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
252a673d
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
252a673d
编写于
9月 13, 2018
作者:
A
Alex Dima
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixes #58612: Detect when the extension host is unresponsive
上级
c0bbadd9
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
193 addition
and
48 deletion
+193
-48
src/vs/workbench/parts/extensions/electron-browser/extensionProfileService.ts
...ts/extensions/electron-browser/extensionProfileService.ts
+2
-1
src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts
...ts/extensions/electron-browser/extensions.contribution.ts
+2
-1
src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts
...ts/extensions/electron-browser/runtimeExtensionsEditor.ts
+1
-41
src/vs/workbench/services/extensions/electron-browser/extensionHost.ts
...nch/services/extensions/electron-browser/extensionHost.ts
+2
-2
src/vs/workbench/services/extensions/electron-browser/extensionService.ts
.../services/extensions/electron-browser/extensionService.ts
+56
-2
src/vs/workbench/services/extensions/electron-browser/runtimeExtensionsInput.ts
...ces/extensions/electron-browser/runtimeExtensionsInput.ts
+50
-0
src/vs/workbench/services/extensions/node/rpcProtocol.ts
src/vs/workbench/services/extensions/node/rpcProtocol.ts
+80
-1
未找到文件。
src/vs/workbench/parts/extensions/electron-browser/extensionProfileService.ts
浏览文件 @
252a673d
...
...
@@ -15,12 +15,13 @@ import { append, $, addDisposableListener } from 'vs/base/browser/dom';
import
{
IStatusbarRegistry
,
StatusbarItemDescriptor
,
Extensions
,
IStatusbarItem
}
from
'
vs/workbench/browser/parts/statusbar/statusbar
'
;
import
{
StatusbarAlignment
}
from
'
vs/platform/statusbar/common/statusbar
'
;
import
{
Registry
}
from
'
vs/platform/registry/common/platform
'
;
import
{
IExtensionHostProfileService
,
ProfileSessionState
,
RuntimeExtensionsInput
}
from
'
vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor
'
;
import
{
IExtensionHostProfileService
,
ProfileSessionState
}
from
'
vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor
'
;
import
{
IEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IWindowsService
}
from
'
vs/platform/windows/common/windows
'
;
import
{
IDialogService
}
from
'
vs/platform/dialogs/common/dialogs
'
;
import
{
randomPort
}
from
'
vs/base/node/ports
'
;
import
product
from
'
vs/platform/node/product
'
;
import
{
RuntimeExtensionsInput
}
from
'
vs/workbench/services/extensions/electron-browser/runtimeExtensionsInput
'
;
export
class
ExtensionHostProfileService
extends
Disposable
implements
IExtensionHostProfileService
{
...
...
src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts
浏览文件 @
252a673d
...
...
@@ -38,9 +38,10 @@ import { areSameExtensions } from 'vs/platform/extensionManagement/common/extens
import
{
GalleryExtensionsHandler
,
ExtensionsHandler
}
from
'
vs/workbench/parts/extensions/browser/extensionsQuickOpen
'
;
import
{
EditorDescriptor
,
IEditorRegistry
,
Extensions
as
EditorExtensions
}
from
'
vs/workbench/browser/editor
'
;
import
{
LifecyclePhase
}
from
'
vs/platform/lifecycle/common/lifecycle
'
;
import
{
RuntimeExtensionsEditor
,
RuntimeExtensionsInput
,
ShowRuntimeExtensionsAction
,
IExtensionHostProfileService
}
from
'
vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor
'
;
import
{
RuntimeExtensionsEditor
,
ShowRuntimeExtensionsAction
,
IExtensionHostProfileService
}
from
'
vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor
'
;
import
{
EditorInput
,
IEditorInputFactory
,
IEditorInputFactoryRegistry
,
Extensions
as
EditorInputExtensions
}
from
'
vs/workbench/common/editor
'
;
import
{
ExtensionHostProfileService
}
from
'
vs/workbench/parts/extensions/electron-browser/extensionProfileService
'
;
import
{
RuntimeExtensionsInput
}
from
'
vs/workbench/services/extensions/electron-browser/runtimeExtensionsInput
'
;
// Singletons
registerSingleton
(
IExtensionsWorkbenchService
,
ExtensionsWorkbenchService
);
...
...
src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts
浏览文件 @
252a673d
...
...
@@ -9,8 +9,6 @@ import 'vs/css!./media/runtimeExtensionsEditor';
import
*
as
nls
from
'
vs/nls
'
;
import
*
as
os
from
'
os
'
;
import
product
from
'
vs/platform/node/product
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
EditorInput
}
from
'
vs/workbench/common/editor
'
;
import
pkg
from
'
vs/platform/node/package
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
Action
,
IAction
}
from
'
vs/base/common/actions
'
;
...
...
@@ -38,6 +36,7 @@ import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import
{
Event
}
from
'
vs/base/common/event
'
;
import
{
DisableForWorkspaceAction
,
DisableGloballyAction
}
from
'
vs/workbench/parts/extensions/electron-browser/extensionsActions
'
;
import
{
INotificationService
}
from
'
vs/platform/notification/common/notification
'
;
import
{
RuntimeExtensionsInput
}
from
'
vs/workbench/services/extensions/electron-browser/runtimeExtensionsInput
'
;
export
const
IExtensionHostProfileService
=
createDecorator
<
IExtensionHostProfileService
>
(
'
extensionHostProfileService
'
);
...
...
@@ -430,45 +429,6 @@ export class RuntimeExtensionsEditor extends BaseEditor {
}
}
export
class
RuntimeExtensionsInput
extends
EditorInput
{
static
readonly
ID
=
'
workbench.runtimeExtensions.input
'
;
constructor
()
{
super
();
}
getTypeId
():
string
{
return
RuntimeExtensionsInput
.
ID
;
}
getName
():
string
{
return
nls
.
localize
(
'
extensionsInputName
'
,
"
Running Extensions
"
);
}
matches
(
other
:
any
):
boolean
{
if
(
!
(
other
instanceof
RuntimeExtensionsInput
))
{
return
false
;
}
return
true
;
}
resolve
():
TPromise
<
any
>
{
return
TPromise
.
as
(
null
);
}
supportsSplitEditor
():
boolean
{
return
false
;
}
getResource
():
URI
{
return
URI
.
from
({
scheme
:
'
runtime-extensions
'
,
path
:
'
default
'
});
}
}
export
class
ShowRuntimeExtensionsAction
extends
Action
{
static
readonly
ID
=
'
workbench.action.showRuntimeExtensions
'
;
static
LABEL
=
nls
.
localize
(
'
showRuntimeExtensions
'
,
"
Show Running Extensions
"
);
...
...
src/vs/workbench/services/extensions/electron-browser/extensionHost.ts
浏览文件 @
252a673d
...
...
@@ -490,9 +490,9 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
// (graceful termination)
protocol
.
send
(
createMessageOfType
(
MessageType
.
Terminate
));
// Give the extension host
6
0s, after which we will
// Give the extension host
1
0s, after which we will
// try to kill the process and release any resources
setTimeout
(()
=>
this
.
_cleanResources
(),
6
0
*
1000
);
setTimeout
(()
=>
this
.
_cleanResources
(),
1
0
*
1000
);
},
(
err
)
=>
{
...
...
src/vs/workbench/services/extensions/electron-browser/extensionService.ts
浏览文件 @
252a673d
...
...
@@ -39,12 +39,14 @@ import { Event, Emitter } from 'vs/base/common/event';
import
{
ExtensionHostProfiler
}
from
'
vs/workbench/services/extensions/electron-browser/extensionHostProfiler
'
;
import
product
from
'
vs/platform/node/product
'
;
import
*
as
strings
from
'
vs/base/common/strings
'
;
import
{
RPCProtocol
,
IRPCProtocolLogger
,
RequestInitiator
}
from
'
vs/workbench/services/extensions/node/rpcProtocol
'
;
import
{
INotificationService
,
Severity
}
from
'
vs/platform/notification/common/notification
'
;
import
{
RPCProtocol
,
IRPCProtocolLogger
,
RequestInitiator
,
ResponsiveState
}
from
'
vs/workbench/services/extensions/node/rpcProtocol
'
;
import
{
INotificationService
,
Severity
,
INotificationHandle
}
from
'
vs/platform/notification/common/notification
'
;
import
{
isFalsyOrEmpty
}
from
'
vs/base/common/arrays
'
;
import
{
Schemas
}
from
'
vs/base/common/network
'
;
import
{
getPathFromAmdModule
}
from
'
vs/base/common/amd
'
;
import
{
isEqualOrParent
}
from
'
vs/base/common/resources
'
;
import
{
IEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
RuntimeExtensionsInput
}
from
'
vs/workbench/services/extensions/electron-browser/runtimeExtensionsInput
'
;
// Enable to see detailed message communication between window and extension host
const
LOG_EXTENSION_HOST_COMMUNICATION
=
false
;
...
...
@@ -115,6 +117,9 @@ export class ExtensionHostProcessManager extends Disposable {
public
readonly
onDidCrash
:
Event
<
[
number
,
string
]
>
;
private
readonly
_onDidChangeResponsiveState
:
Emitter
<
ResponsiveState
>
=
this
.
_register
(
new
Emitter
<
ResponsiveState
>
());
public
readonly
onDidChangeResponsiveState
:
Event
<
ResponsiveState
>
=
this
.
_onDidChangeResponsiveState
.
event
;
/**
* A map of already activated events to speed things up if the same activation event is triggered multiple times.
*/
...
...
@@ -187,6 +192,7 @@ export class ExtensionHostProcessManager extends Disposable {
}
this
.
_extensionHostProcessRPCProtocol
=
new
RPCProtocol
(
protocol
,
logger
);
this
.
_register
(
this
.
_extensionHostProcessRPCProtocol
.
onDidChangeResponsiveState
((
responsiveState
:
ResponsiveState
)
=>
this
.
_onDidChangeResponsiveState
.
fire
(
responsiveState
)));
const
extHostContext
:
IExtHostContext
=
{
getProxy
:
<
T
>
(
identifier
:
ProxyIdentifier
<
T
>
):
T
=>
this
.
_extensionHostProcessRPCProtocol
.
getProxy
(
identifier
),
set
:
<
T
,
R
extends
T
>
(
identifier
:
ProxyIdentifier
<
T
>
,
instance
:
R
):
R
=>
this
.
_extensionHostProcessRPCProtocol
.
set
(
identifier
,
instance
),
...
...
@@ -262,6 +268,8 @@ export class ExtensionService extends Disposable implements IExtensionService {
private
readonly
_onDidChangeExtensionsStatus
:
Emitter
<
string
[]
>
=
this
.
_register
(
new
Emitter
<
string
[]
>
());
public
readonly
onDidChangeExtensionsStatus
:
Event
<
string
[]
>
=
this
.
_onDidChangeExtensionsStatus
.
event
;
private
_unresponsiveNotificationHandle
:
INotificationHandle
;
// --- Members used per extension host process
private
_extensionHostProcessManagers
:
ExtensionHostProcessManager
[];
private
_extensionHostProcessActivationTimes
:
{
[
id
:
string
]:
ActivationTimes
;
};
...
...
@@ -288,6 +296,8 @@ export class ExtensionService extends Disposable implements IExtensionService {
this
.
_onDidRegisterExtensions
=
new
Emitter
<
void
>
();
this
.
_unresponsiveNotificationHandle
=
null
;
this
.
_extensionHostProcessManagers
=
[];
this
.
_extensionHostProcessActivationTimes
=
Object
.
create
(
null
);
this
.
_extensionHostExtensionRuntimeErrors
=
Object
.
create
(
null
);
...
...
@@ -375,6 +385,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
const
extHostProcessWorker
=
this
.
_instantiationService
.
createInstance
(
ExtensionHostProcessWorker
,
this
.
getExtensions
(),
this
.
_extensionHostLogsLocation
);
const
extHostProcessManager
=
this
.
_instantiationService
.
createInstance
(
ExtensionHostProcessManager
,
extHostProcessWorker
,
initialActivationEvents
);
extHostProcessManager
.
onDidCrash
(([
code
,
signal
])
=>
this
.
_onExtensionHostCrashed
(
code
,
signal
));
extHostProcessManager
.
onDidChangeResponsiveState
((
responsiveState
)
=>
this
.
_onResponsiveStateChanged
(
responsiveState
));
this
.
_extensionHostProcessManagers
.
push
(
extHostProcessManager
);
}
...
...
@@ -399,6 +410,49 @@ export class ExtensionService extends Disposable implements IExtensionService {
);
}
private
_onResponsiveStateChanged
(
state
:
ResponsiveState
):
void
{
if
(
this
.
_unresponsiveNotificationHandle
)
{
this
.
_unresponsiveNotificationHandle
.
close
();
this
.
_unresponsiveNotificationHandle
=
null
;
}
const
showRunningExtensions
=
{
keepOpen
:
true
,
label
:
nls
.
localize
(
'
extensionHostProcess.unresponsive.inspect
'
,
"
Show running extensions
"
),
run
:
()
=>
{
this
.
_instantiationService
.
invokeFunction
((
accessor
)
=>
{
const
editorService
=
accessor
.
get
(
IEditorService
);
editorService
.
openEditor
(
this
.
_instantiationService
.
createInstance
(
RuntimeExtensionsInput
),
{
revealIfOpened
:
true
});
// keepOpen does not appear to work
setTimeout
(()
=>
{
this
.
_onResponsiveStateChanged
(
state
);
},
100
);
});
}
};
const
restartExtensionHost
=
{
label
:
nls
.
localize
(
'
extensionHostProcess.unresponsive.restart
'
,
"
Restart Extension Host
"
),
run
:
()
=>
{
this
.
restartExtensionHost
();
}
};
if
(
state
===
ResponsiveState
.
Unresponsive
)
{
this
.
_unresponsiveNotificationHandle
=
this
.
_notificationService
.
prompt
(
Severity
.
Warning
,
nls
.
localize
(
'
extensionHostProcess.unresponsive
'
,
"
Extension Host is unresponsive.
"
),
[
showRunningExtensions
,
restartExtensionHost
]
);
}
else
{
this
.
_unresponsiveNotificationHandle
=
this
.
_notificationService
.
prompt
(
Severity
.
Info
,
nls
.
localize
(
'
extensionHostProcess.responsive
'
,
"
Extension Host is now responsive.
"
),
[
showRunningExtensions
]
);
}
}
// ---- begin IExtensionService
public
activateByEvent
(
activationEvent
:
string
):
TPromise
<
void
>
{
...
...
src/vs/workbench/services/extensions/electron-browser/runtimeExtensionsInput.ts
0 → 100644
浏览文件 @
252a673d
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
*
as
nls
from
'
vs/nls
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
EditorInput
}
from
'
vs/workbench/common/editor
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
export
class
RuntimeExtensionsInput
extends
EditorInput
{
static
readonly
ID
=
'
workbench.runtimeExtensions.input
'
;
constructor
()
{
super
();
}
getTypeId
():
string
{
return
RuntimeExtensionsInput
.
ID
;
}
getName
():
string
{
return
nls
.
localize
(
'
extensionsInputName
'
,
"
Running Extensions
"
);
}
matches
(
other
:
any
):
boolean
{
if
(
!
(
other
instanceof
RuntimeExtensionsInput
))
{
return
false
;
}
return
true
;
}
resolve
():
TPromise
<
any
>
{
return
TPromise
.
as
(
null
);
}
supportsSplitEditor
():
boolean
{
return
false
;
}
getResource
():
URI
{
return
URI
.
from
({
scheme
:
'
runtime-extensions
'
,
path
:
'
default
'
});
}
}
src/vs/workbench/services/extensions/node/rpcProtocol.ts
浏览文件 @
252a673d
...
...
@@ -14,6 +14,9 @@ import { URI } from 'vs/base/common/uri';
import
{
MarshalledObject
}
from
'
vs/base/common/marshalling
'
;
import
{
IURITransformer
}
from
'
vs/base/common/uriIpc
'
;
import
{
CancellationToken
,
CancellationTokenSource
}
from
'
vs/base/common/cancellation
'
;
import
{
RunOnceScheduler
}
from
'
vs/base/common/async
'
;
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
Event
,
Emitter
}
from
'
vs/base/common/event
'
;
declare
var
Proxy
:
any
;
// TODO@TypeScript
...
...
@@ -91,6 +94,11 @@ export const enum RequestInitiator {
OtherSide
=
1
}
export
const
enum
ResponsiveState
{
Responsive
=
0
,
Unresponsive
=
1
}
export
interface
IRPCProtocolLogger
{
logIncoming
(
msgLength
:
number
,
req
:
number
,
initiator
:
RequestInitiator
,
str
:
string
,
data
?:
any
):
void
;
logOutgoing
(
msgLength
:
number
,
req
:
number
,
initiator
:
RequestInitiator
,
str
:
string
,
data
?:
any
):
void
;
...
...
@@ -98,7 +106,12 @@ export interface IRPCProtocolLogger {
const
noop
=
()
=>
{
};
export
class
RPCProtocol
implements
IRPCProtocol
{
export
class
RPCProtocol
extends
Disposable
implements
IRPCProtocol
{
private
static
UNRESPONSIVE_TIME
=
10
*
1000
;
// 10s
private
readonly
_onDidChangeResponsiveState
:
Emitter
<
ResponsiveState
>
=
this
.
_register
(
new
Emitter
<
ResponsiveState
>
());
public
readonly
onDidChangeResponsiveState
:
Event
<
ResponsiveState
>
=
this
.
_onDidChangeResponsiveState
.
event
;
private
readonly
_protocol
:
IMessagePassingProtocol
;
private
readonly
_logger
:
IRPCProtocolLogger
;
...
...
@@ -109,8 +122,13 @@ export class RPCProtocol implements IRPCProtocol {
private
_lastMessageId
:
number
;
private
readonly
_cancelInvokedHandlers
:
{
[
req
:
string
]:
()
=>
void
;
};
private
readonly
_pendingRPCReplies
:
{
[
msgId
:
string
]:
LazyPromise
;
};
private
_responsiveState
:
ResponsiveState
;
private
_pendingRPCRepliesCount
:
number
;
private
_unresponsiveTime
:
number
;
private
_asyncCheckUresponsive
:
RunOnceScheduler
;
constructor
(
protocol
:
IMessagePassingProtocol
,
logger
:
IRPCProtocolLogger
=
null
,
transformer
:
IURITransformer
=
null
)
{
super
();
this
.
_protocol
=
protocol
;
this
.
_logger
=
logger
;
this
.
_uriTransformer
=
transformer
;
...
...
@@ -124,6 +142,10 @@ export class RPCProtocol implements IRPCProtocol {
this
.
_lastMessageId
=
0
;
this
.
_cancelInvokedHandlers
=
Object
.
create
(
null
);
this
.
_pendingRPCReplies
=
{};
this
.
_responsiveState
=
ResponsiveState
.
Responsive
;
this
.
_pendingRPCRepliesCount
=
0
;
this
.
_unresponsiveTime
=
0
;
this
.
_asyncCheckUresponsive
=
this
.
_register
(
new
RunOnceScheduler
(()
=>
this
.
_checkUnresponsive
(),
1000
));
this
.
_protocol
.
onMessage
((
msg
)
=>
this
.
_receiveOneMessage
(
msg
));
}
...
...
@@ -137,6 +159,60 @@ export class RPCProtocol implements IRPCProtocol {
});
}
private
_onWillSendRequest
():
void
{
if
(
this
.
_pendingRPCRepliesCount
===
0
)
{
// Since this is the first request we are sending in a while,
// mark this moment as the start for the countdown to unresponsive time
this
.
_unresponsiveTime
=
Date
.
now
()
+
RPCProtocol
.
UNRESPONSIVE_TIME
;
}
this
.
_pendingRPCRepliesCount
++
;
if
(
!
this
.
_asyncCheckUresponsive
.
isScheduled
())
{
this
.
_asyncCheckUresponsive
.
schedule
();
}
}
private
_onWillReceiveReply
():
void
{
// The next possible unresponsive time is now + delta.
this
.
_unresponsiveTime
=
Date
.
now
()
+
RPCProtocol
.
UNRESPONSIVE_TIME
;
this
.
_pendingRPCRepliesCount
--
;
if
(
this
.
_pendingRPCRepliesCount
===
0
)
{
// No more need to check for unresponsive
this
.
_asyncCheckUresponsive
.
cancel
();
}
// The ext host is responsive!
this
.
_setResponsiveState
(
ResponsiveState
.
Responsive
);
}
private
_checkUnresponsive
():
void
{
if
(
this
.
_pendingRPCRepliesCount
===
0
)
{
// Not waiting for anything => cannot say if it is responsive or not
return
;
}
if
(
Date
.
now
()
>
this
.
_unresponsiveTime
)
{
// Unresponsive!!
this
.
_setResponsiveState
(
ResponsiveState
.
Unresponsive
);
}
else
{
// Not (yet) unresponsive, be sure to check again soon
if
(
this
.
_pendingRPCRepliesCount
>
0
)
{
this
.
_asyncCheckUresponsive
.
schedule
();
}
}
}
private
_setResponsiveState
(
newResponsiveState
:
ResponsiveState
):
void
{
if
(
this
.
_responsiveState
===
newResponsiveState
)
{
// no change
return
;
}
this
.
_responsiveState
=
newResponsiveState
;
this
.
_onDidChangeResponsiveState
.
fire
(
this
.
_responsiveState
);
}
public
get
responsiveState
():
ResponsiveState
{
return
this
.
_responsiveState
;
}
public
transformIncomingURIs
<
T
>
(
obj
:
T
):
T
{
if
(
!
this
.
_uriTransformer
)
{
return
obj
;
...
...
@@ -307,6 +383,7 @@ export class RPCProtocol implements IRPCProtocol {
const
pendingReply
=
this
.
_pendingRPCReplies
[
callId
];
delete
this
.
_pendingRPCReplies
[
callId
];
this
.
_onWillReceiveReply
();
pendingReply
.
resolveOk
(
value
);
}
...
...
@@ -323,6 +400,7 @@ export class RPCProtocol implements IRPCProtocol {
const
pendingReply
=
this
.
_pendingRPCReplies
[
callId
];
delete
this
.
_pendingRPCReplies
[
callId
];
this
.
_onWillReceiveReply
();
let
err
:
Error
=
null
;
if
(
value
&&
value
.
$isError
)
{
...
...
@@ -383,6 +461,7 @@ export class RPCProtocol implements IRPCProtocol {
}
this
.
_pendingRPCReplies
[
callId
]
=
result
;
this
.
_onWillSendRequest
();
if
(
this
.
_uriTransformer
)
{
args
=
transformOutgoingURIs
(
args
,
this
.
_uriTransformer
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录