Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
23fe7a39
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,发现更多精彩内容 >>
提交
23fe7a39
编写于
8月 26, 2020
作者:
M
Matt Bierner
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Split extHost webview panels to own file
上级
72cbf699
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
330 addition
and
290 deletion
+330
-290
src/vs/workbench/api/common/extHost.api.impl.ts
src/vs/workbench/api/common/extHost.api.impl.ts
+5
-4
src/vs/workbench/api/common/extHostCustomEditors.ts
src/vs/workbench/api/common/extHostCustomEditors.ts
+4
-2
src/vs/workbench/api/common/extHostWebview.ts
src/vs/workbench/api/common/extHostWebview.ts
+6
-277
src/vs/workbench/api/common/extHostWebviewPanels.ts
src/vs/workbench/api/common/extHostWebviewPanels.ts
+299
-0
src/vs/workbench/test/browser/api/extHostWebview.test.ts
src/vs/workbench/test/browser/api/extHostWebview.test.ts
+16
-7
未找到文件。
src/vs/workbench/api/common/extHost.api.impl.ts
浏览文件 @
23fe7a39
...
...
@@ -78,6 +78,7 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa
import
{
IExtHostConsumerFileSystem
}
from
'
vs/workbench/api/common/extHostFileSystemConsumer
'
;
import
{
ExtHostWebviewViews
}
from
'
vs/workbench/api/common/extHostWebviewView
'
;
import
{
ExtHostCustomEditors
}
from
'
vs/workbench/api/common/extHostCustomEditors
'
;
import
{
ExtHostWebviewPanels
}
from
'
vs/workbench/api/common/extHostWebviewPanels
'
;
export
interface
IExtensionApiFactory
{
(
extension
:
IExtensionDescription
,
registry
:
ExtensionDescriptionRegistry
,
configProvider
:
ExtHostConfigProvider
):
typeof
vscode
;
...
...
@@ -144,8 +145,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const
extHostAuthentication
=
rpcProtocol
.
set
(
ExtHostContext
.
ExtHostAuthentication
,
new
ExtHostAuthentication
(
rpcProtocol
));
const
extHostTimeline
=
rpcProtocol
.
set
(
ExtHostContext
.
ExtHostTimeline
,
new
ExtHostTimeline
(
rpcProtocol
,
extHostCommands
));
const
extHostWebviews
=
rpcProtocol
.
set
(
ExtHostContext
.
ExtHostWebviews
,
new
ExtHostWebviews
(
rpcProtocol
,
initData
.
environment
,
extHostWorkspace
,
extHostLogService
,
extHostApiDeprecation
));
rpcProtocol
.
set
(
ExtHostContext
.
ExtHostWebviewPanels
,
extHostWebviews
);
const
extHostCustomEditors
=
rpcProtocol
.
set
(
ExtHostContext
.
ExtHostCustomEditors
,
new
ExtHostCustomEditors
(
rpcProtocol
,
extHostDocuments
,
extensionStoragePaths
,
extHostWebviews
));
const
extHostWebviewPanels
=
rpcProtocol
.
set
(
ExtHostContext
.
ExtHostWebviewPanels
,
new
ExtHostWebviewPanels
(
rpcProtocol
,
extHostWebviews
,
extHostWorkspace
)
);
const
extHostCustomEditors
=
rpcProtocol
.
set
(
ExtHostContext
.
ExtHostCustomEditors
,
new
ExtHostCustomEditors
(
rpcProtocol
,
extHostDocuments
,
extensionStoragePaths
,
extHostWebviews
,
extHostWebviewPanels
));
const
extHostWebviewViews
=
rpcProtocol
.
set
(
ExtHostContext
.
ExtHostWebviewViews
,
new
ExtHostWebviewViews
(
rpcProtocol
,
extHostWebviews
));
// Check that no named customers are missing
...
...
@@ -569,7 +570,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return
extHostOutputService
.
createOutputChannel
(
name
);
},
createWebviewPanel
(
viewType
:
string
,
title
:
string
,
showOptions
:
vscode
.
ViewColumn
|
{
viewColumn
:
vscode
.
ViewColumn
,
preserveFocus
?:
boolean
},
options
?:
vscode
.
WebviewPanelOptions
&
vscode
.
WebviewOptions
):
vscode
.
WebviewPanel
{
return
extHostWebviews
.
createWebviewPanel
(
extension
,
viewType
,
title
,
showOptions
,
options
);
return
extHostWebview
Panel
s
.
createWebviewPanel
(
extension
,
viewType
,
title
,
showOptions
,
options
);
},
createWebviewTextEditorInset
(
editor
:
vscode
.
TextEditor
,
line
:
number
,
height
:
number
,
options
?:
vscode
.
WebviewOptions
):
vscode
.
WebviewEditorInset
{
checkProposedApiEnabled
(
extension
);
...
...
@@ -594,7 +595,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return
extHostTreeViews
.
createTreeView
(
viewId
,
options
,
extension
);
},
registerWebviewPanelSerializer
:
(
viewType
:
string
,
serializer
:
vscode
.
WebviewPanelSerializer
)
=>
{
return
extHostWebviews
.
registerWebviewPanelSerializer
(
extension
,
viewType
,
serializer
);
return
extHostWebview
Panel
s
.
registerWebviewPanelSerializer
(
extension
,
viewType
,
serializer
);
},
registerCustomEditorProvider
:
(
viewType
:
string
,
provider
:
vscode
.
CustomTextEditorProvider
|
vscode
.
CustomReadonlyEditorProvider
,
options
:
{
webviewOptions
?:
vscode
.
WebviewPanelOptions
,
supportsMultipleEditorsPerDocument
?:
boolean
}
=
{})
=>
{
return
extHostCustomEditors
.
registerCustomEditorProvider
(
extension
,
viewType
,
provider
,
options
);
...
...
src/vs/workbench/api/common/extHostCustomEditors.ts
浏览文件 @
23fe7a39
...
...
@@ -14,6 +14,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'
import
{
ExtHostDocuments
}
from
'
vs/workbench/api/common/extHostDocuments
'
;
import
{
IExtensionStoragePaths
}
from
'
vs/workbench/api/common/extHostStoragePaths
'
;
import
{
ExtHostWebviews
,
toExtensionData
}
from
'
vs/workbench/api/common/extHostWebview
'
;
import
{
ExtHostWebviewPanels
}
from
'
vs/workbench/api/common/extHostWebviewPanels
'
;
import
{
EditorViewColumn
}
from
'
vs/workbench/api/common/shared/editor
'
;
import
type
*
as
vscode
from
'
vscode
'
;
import
{
Cache
}
from
'
./cache
'
;
...
...
@@ -165,6 +166,7 @@ export class ExtHostCustomEditors implements extHostProtocol.ExtHostCustomEditor
private
readonly
_extHostDocuments
:
ExtHostDocuments
,
private
readonly
_extensionStoragePaths
:
IExtensionStoragePaths
|
undefined
,
private
readonly
_extHostWebview
:
ExtHostWebviews
,
private
readonly
_extHostWebviewPanels
:
ExtHostWebviewPanels
,
)
{
this
.
_proxy
=
mainContext
.
getProxy
(
extHostProtocol
.
MainContext
.
MainThreadCustomEditors
);
}
...
...
@@ -260,7 +262,7 @@ export class ExtHostCustomEditors implements extHostProtocol.ExtHostCustomEditor
}
const
webview
=
this
.
_extHostWebview
.
createNewWebview
(
handle
,
options
,
entry
.
extension
);
const
panel
=
this
.
_extHostWebview
.
createNewWebviewPanel
(
handle
,
viewType
,
title
,
position
,
options
,
webview
);
const
panel
=
this
.
_extHostWebview
Panels
.
createNewWebviewPanel
(
handle
,
viewType
,
title
,
position
,
options
,
webview
);
const
revivedResource
=
URI
.
revive
(
resource
);
...
...
@@ -297,7 +299,7 @@ export class ExtHostCustomEditors implements extHostProtocol.ExtHostCustomEditor
throw
new
Error
(
`Provider does not implement move '
${
viewType
}
'`
);
}
const
webview
=
this
.
_extHostWebview
.
getWebviewPanel
(
handle
);
const
webview
=
this
.
_extHostWebview
Panels
.
getWebviewPanel
(
handle
);
if
(
!
webview
)
{
throw
new
Error
(
`No webview found`
);
}
...
...
src/vs/workbench/api/common/extHostWebview.ts
浏览文件 @
23fe7a39
...
...
@@ -4,20 +4,15 @@
*--------------------------------------------------------------------------------------------*/
import
{
Emitter
,
Event
}
from
'
vs/base/common/event
'
;
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
generateUuid
}
from
'
vs/base/common/uuid
'
;
import
*
as
modes
from
'
vs/editor/common/modes
'
;
import
{
IExtensionDescription
}
from
'
vs/platform/extensions/common/extensions
'
;
import
{
ILogService
}
from
'
vs/platform/log/common/log
'
;
import
{
IExtHostApiDeprecationService
}
from
'
vs/workbench/api/common/extHostApiDeprecationService
'
;
import
*
as
typeConverters
from
'
vs/workbench/api/common/extHostTypeConverters
'
;
import
{
IExtHostWorkspace
}
from
'
vs/workbench/api/common/extHostWorkspace
'
;
import
{
EditorViewColumn
}
from
'
vs/workbench/api/common/shared/editor
'
;
import
{
asWebviewUri
,
WebviewInitData
}
from
'
vs/workbench/api/common/shared/webview
'
;
import
type
*
as
vscode
from
'
vscode
'
;
import
*
as
extHostProtocol
from
'
./extHost.protocol
'
;
import
*
as
extHostTypes
from
'
./extHostTypes
'
;
export
class
ExtHostWebview
implements
vscode
.
Webview
{
...
...
@@ -116,169 +111,11 @@ export class ExtHostWebview implements vscode.Webview {
}
}
type
IconPath
=
URI
|
{
light
:
URI
,
dark
:
URI
};
export
class
ExtHostWebviews
implements
extHostProtocol
.
ExtHostWebviewsShape
{
class
ExtHostWebviewPanel
extends
Disposable
implements
vscode
.
WebviewPanel
{
readonly
#
handle
:
extHostProtocol
.
WebviewHandle
;
readonly
#
proxy
:
extHostProtocol
.
MainThreadWebviewPanelsShape
;
readonly
#
viewType
:
string
;
readonly
#
webview
:
ExtHostWebview
;
readonly
#
options
:
vscode
.
WebviewPanelOptions
;
#
title
:
string
;
#
iconPath
?:
IconPath
;
#
viewColumn
:
vscode
.
ViewColumn
|
undefined
=
undefined
;
#
visible
:
boolean
=
true
;
#
active
:
boolean
=
true
;
#
isDisposed
:
boolean
=
false
;
readonly
#
onDidDispose
=
this
.
_register
(
new
Emitter
<
void
>
());
public
readonly
onDidDispose
=
this
.
#
onDidDispose
.
event
;
readonly
#
onDidChangeViewState
=
this
.
_register
(
new
Emitter
<
vscode
.
WebviewPanelOnDidChangeViewStateEvent
>
());
public
readonly
onDidChangeViewState
=
this
.
#
onDidChangeViewState
.
event
;
constructor
(
handle
:
extHostProtocol
.
WebviewHandle
,
proxy
:
extHostProtocol
.
MainThreadWebviewPanelsShape
,
viewType
:
string
,
title
:
string
,
viewColumn
:
vscode
.
ViewColumn
|
undefined
,
editorOptions
:
vscode
.
WebviewPanelOptions
,
webview
:
ExtHostWebview
)
{
super
();
this
.
#
handle
=
handle
;
this
.
#
proxy
=
proxy
;
this
.
#
viewType
=
viewType
;
this
.
#
options
=
editorOptions
;
this
.
#
viewColumn
=
viewColumn
;
this
.
#
title
=
title
;
this
.
#
webview
=
webview
;
}
public
dispose
()
{
if
(
this
.
#
isDisposed
)
{
return
;
}
this
.
#
isDisposed
=
true
;
this
.
#
onDidDispose
.
fire
();
this
.
#
proxy
.
$disposeWebview
(
this
.
#
handle
);
this
.
#
webview
.
dispose
();
super
.
dispose
();
}
get
webview
()
{
this
.
assertNotDisposed
();
return
this
.
#
webview
;
}
get
viewType
():
string
{
this
.
assertNotDisposed
();
return
this
.
#
viewType
;
}
get
title
():
string
{
this
.
assertNotDisposed
();
return
this
.
#
title
;
}
set
title
(
value
:
string
)
{
this
.
assertNotDisposed
();
if
(
this
.
#
title
!==
value
)
{
this
.
#
title
=
value
;
this
.
#
proxy
.
$setTitle
(
this
.
#
handle
,
value
);
}
}
get
iconPath
():
IconPath
|
undefined
{
this
.
assertNotDisposed
();
return
this
.
#
iconPath
;
}
set
iconPath
(
value
:
IconPath
|
undefined
)
{
this
.
assertNotDisposed
();
if
(
this
.
#
iconPath
!==
value
)
{
this
.
#
iconPath
=
value
;
this
.
#
proxy
.
$setIconPath
(
this
.
#
handle
,
URI
.
isUri
(
value
)
?
{
light
:
value
,
dark
:
value
}
:
value
);
}
}
get
options
()
{
return
this
.
#
options
;
}
get
viewColumn
():
vscode
.
ViewColumn
|
undefined
{
this
.
assertNotDisposed
();
if
(
typeof
this
.
#
viewColumn
===
'
number
'
&&
this
.
#
viewColumn
<
0
)
{
// We are using a symbolic view column
// Return undefined instead to indicate that the real view column is currently unknown but will be resolved.
return
undefined
;
}
return
this
.
#
viewColumn
;
}
public
get
active
():
boolean
{
this
.
assertNotDisposed
();
return
this
.
#
active
;
}
public
get
visible
():
boolean
{
this
.
assertNotDisposed
();
return
this
.
#
visible
;
}
_updateViewState
(
newState
:
{
active
:
boolean
;
visible
:
boolean
;
viewColumn
:
vscode
.
ViewColumn
;
})
{
if
(
this
.
#
isDisposed
)
{
return
;
}
if
(
this
.
active
!==
newState
.
active
||
this
.
visible
!==
newState
.
visible
||
this
.
viewColumn
!==
newState
.
viewColumn
)
{
this
.
#
active
=
newState
.
active
;
this
.
#
visible
=
newState
.
visible
;
this
.
#
viewColumn
=
newState
.
viewColumn
;
this
.
#
onDidChangeViewState
.
fire
({
webviewPanel
:
this
});
}
}
public
reveal
(
viewColumn
?:
vscode
.
ViewColumn
,
preserveFocus
?:
boolean
):
void
{
this
.
assertNotDisposed
();
this
.
#
proxy
.
$reveal
(
this
.
#
handle
,
{
viewColumn
:
viewColumn
?
typeConverters
.
ViewColumn
.
from
(
viewColumn
)
:
undefined
,
preserveFocus
:
!!
preserveFocus
});
}
private
assertNotDisposed
()
{
if
(
this
.
#
isDisposed
)
{
throw
new
Error
(
'
Webview is disposed
'
);
}
}
}
export
class
ExtHostWebviews
implements
extHostProtocol
.
ExtHostWebviewsShape
,
extHostProtocol
.
ExtHostWebviewPanelsShape
{
private
static
newHandle
():
extHostProtocol
.
WebviewHandle
{
return
generateUuid
();
}
private
readonly
_proxy
:
extHostProtocol
.
MainThreadWebviewPanelsShape
;
private
readonly
_webviewProxy
:
extHostProtocol
.
MainThreadWebviewsShape
;
private
readonly
_webviews
=
new
Map
<
extHostProtocol
.
WebviewHandle
,
ExtHostWebview
>
();
private
readonly
_webviewPanels
=
new
Map
<
extHostProtocol
.
WebviewHandle
,
ExtHostWebviewPanel
>
();
private
readonly
_serializers
=
new
Map
<
string
,
{
readonly
serializer
:
vscode
.
WebviewPanelSerializer
;
readonly
extension
:
IExtensionDescription
;
}
>
();
constructor
(
mainContext
:
extHostProtocol
.
IMainContext
,
...
...
@@ -287,32 +124,9 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape, ex
private
readonly
_logService
:
ILogService
,
private
readonly
_deprecationService
:
IExtHostApiDeprecationService
,
)
{
this
.
_proxy
=
mainContext
.
getProxy
(
extHostProtocol
.
MainContext
.
MainThreadWebviewPanels
);
this
.
_webviewProxy
=
mainContext
.
getProxy
(
extHostProtocol
.
MainContext
.
MainThreadWebviews
);
}
public
createWebviewPanel
(
extension
:
IExtensionDescription
,
viewType
:
string
,
title
:
string
,
showOptions
:
vscode
.
ViewColumn
|
{
viewColumn
:
vscode
.
ViewColumn
,
preserveFocus
?:
boolean
},
options
:
(
vscode
.
WebviewPanelOptions
&
vscode
.
WebviewOptions
)
=
{},
):
vscode
.
WebviewPanel
{
const
viewColumn
=
typeof
showOptions
===
'
object
'
?
showOptions
.
viewColumn
:
showOptions
;
const
webviewShowOptions
=
{
viewColumn
:
typeConverters
.
ViewColumn
.
from
(
viewColumn
),
preserveFocus
:
typeof
showOptions
===
'
object
'
&&
!!
showOptions
.
preserveFocus
};
const
handle
=
ExtHostWebviews
.
newHandle
();
this
.
_proxy
.
$createWebviewPanel
(
toExtensionData
(
extension
),
handle
,
viewType
,
title
,
webviewShowOptions
,
convertWebviewOptions
(
extension
,
this
.
workspace
,
options
));
const
webview
=
this
.
createNewWebview
(
handle
,
options
,
extension
);
const
panel
=
this
.
createNewWebviewPanel
(
handle
,
viewType
,
title
,
viewColumn
,
options
,
webview
);
return
panel
;
}
public
$onMessage
(
handle
:
extHostProtocol
.
WebviewHandle
,
message
:
any
...
...
@@ -330,91 +144,6 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape, ex
this
.
_logService
.
warn
(
`
${
extensionId
}
created a webview without a content security policy: https://aka.ms/vscode-webview-missing-csp`
);
}
public
$onDidChangeWebviewPanelViewStates
(
newStates
:
extHostProtocol
.
WebviewPanelViewStateData
):
void
{
const
handles
=
Object
.
keys
(
newStates
);
// Notify webviews of state changes in the following order:
// - Non-visible
// - Visible
// - Active
handles
.
sort
((
a
,
b
)
=>
{
const
stateA
=
newStates
[
a
];
const
stateB
=
newStates
[
b
];
if
(
stateA
.
active
)
{
return
1
;
}
if
(
stateB
.
active
)
{
return
-
1
;
}
return
(
+
stateA
.
visible
)
-
(
+
stateB
.
visible
);
});
for
(
const
handle
of
handles
)
{
const
panel
=
this
.
getWebviewPanel
(
handle
);
if
(
!
panel
)
{
continue
;
}
const
newState
=
newStates
[
handle
];
panel
.
_updateViewState
({
active
:
newState
.
active
,
visible
:
newState
.
visible
,
viewColumn
:
typeConverters
.
ViewColumn
.
to
(
newState
.
position
),
});
}
}
async
$onDidDisposeWebviewPanel
(
handle
:
extHostProtocol
.
WebviewHandle
):
Promise
<
void
>
{
const
panel
=
this
.
getWebviewPanel
(
handle
);
panel
?.
dispose
();
this
.
_webviewPanels
.
delete
(
handle
);
this
.
_webviews
.
delete
(
handle
);
}
public
registerWebviewPanelSerializer
(
extension
:
IExtensionDescription
,
viewType
:
string
,
serializer
:
vscode
.
WebviewPanelSerializer
):
vscode
.
Disposable
{
if
(
this
.
_serializers
.
has
(
viewType
))
{
throw
new
Error
(
`Serializer for '
${
viewType
}
' already registered`
);
}
this
.
_serializers
.
set
(
viewType
,
{
serializer
,
extension
});
this
.
_proxy
.
$registerSerializer
(
viewType
);
return
new
extHostTypes
.
Disposable
(()
=>
{
this
.
_serializers
.
delete
(
viewType
);
this
.
_proxy
.
$unregisterSerializer
(
viewType
);
});
}
async
$deserializeWebviewPanel
(
webviewHandle
:
extHostProtocol
.
WebviewHandle
,
viewType
:
string
,
title
:
string
,
state
:
any
,
position
:
EditorViewColumn
,
options
:
modes
.
IWebviewOptions
&
modes
.
IWebviewPanelOptions
):
Promise
<
void
>
{
const
entry
=
this
.
_serializers
.
get
(
viewType
);
if
(
!
entry
)
{
throw
new
Error
(
`No serializer found for '
${
viewType
}
'`
);
}
const
{
serializer
,
extension
}
=
entry
;
const
webview
=
this
.
createNewWebview
(
webviewHandle
,
options
,
extension
);
const
revivedPanel
=
this
.
createNewWebviewPanel
(
webviewHandle
,
viewType
,
title
,
position
,
options
,
webview
);
await
serializer
.
deserializeWebviewPanel
(
revivedPanel
,
state
);
}
public
createNewWebviewPanel
(
webviewHandle
:
string
,
viewType
:
string
,
title
:
string
,
position
:
number
,
options
:
modes
.
IWebviewOptions
&
modes
.
IWebviewPanelOptions
,
webview
:
ExtHostWebview
)
{
const
panel
=
new
ExtHostWebviewPanel
(
webviewHandle
,
this
.
_proxy
,
viewType
,
title
,
typeof
position
===
'
number
'
&&
position
>=
0
?
typeConverters
.
ViewColumn
.
to
(
position
)
:
undefined
,
options
,
webview
);
this
.
_webviewPanels
.
set
(
webviewHandle
,
panel
);
return
panel
;
}
public
createNewWebview
(
handle
:
string
,
options
:
modes
.
IWebviewOptions
&
modes
.
IWebviewPanelOptions
,
extension
:
IExtensionDescription
):
ExtHostWebview
{
const
webview
=
new
ExtHostWebview
(
handle
,
this
.
_webviewProxy
,
reviveOptions
(
options
),
this
.
initData
,
this
.
workspace
,
extension
,
this
.
_deprecationService
);
this
.
_webviews
.
set
(
handle
,
webview
);
...
...
@@ -424,12 +153,12 @@ export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape, ex
return
webview
;
}
p
rivate
getWebview
(
handle
:
extHostProtocol
.
WebviewHandle
):
ExtHostWebview
|
undefined
{
return
this
.
_webviews
.
get
(
handle
);
p
ublic
deleteWebview
(
handle
:
string
)
{
this
.
_webviews
.
delete
(
handle
);
}
p
ublic
getWebviewPanel
(
handle
:
extHostProtocol
.
WebviewHandle
):
ExtHostWebviewPanel
|
undefined
{
return
this
.
_webview
Panel
s
.
get
(
handle
);
p
rivate
getWebview
(
handle
:
extHostProtocol
.
WebviewHandle
):
ExtHostWebview
|
undefined
{
return
this
.
_webviews
.
get
(
handle
);
}
}
...
...
@@ -437,7 +166,7 @@ export function toExtensionData(extension: IExtensionDescription): extHostProtoc
return
{
id
:
extension
.
identifier
,
location
:
extension
.
extensionLocation
};
}
function
convertWebviewOptions
(
export
function
convertWebviewOptions
(
extension
:
IExtensionDescription
,
workspace
:
IExtHostWorkspace
|
undefined
,
options
:
vscode
.
WebviewPanelOptions
&
vscode
.
WebviewOptions
,
...
...
src/vs/workbench/api/common/extHostWebviewPanels.ts
0 → 100644
浏览文件 @
23fe7a39
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
Emitter
}
from
'
vs/base/common/event
'
;
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
generateUuid
}
from
'
vs/base/common/uuid
'
;
import
*
as
modes
from
'
vs/editor/common/modes
'
;
import
{
IExtensionDescription
}
from
'
vs/platform/extensions/common/extensions
'
;
import
*
as
typeConverters
from
'
vs/workbench/api/common/extHostTypeConverters
'
;
import
{
convertWebviewOptions
,
ExtHostWebview
,
ExtHostWebviews
,
toExtensionData
}
from
'
vs/workbench/api/common/extHostWebview
'
;
import
{
IExtHostWorkspace
}
from
'
vs/workbench/api/common/extHostWorkspace
'
;
import
{
EditorViewColumn
}
from
'
vs/workbench/api/common/shared/editor
'
;
import
type
*
as
vscode
from
'
vscode
'
;
import
*
as
extHostProtocol
from
'
./extHost.protocol
'
;
import
*
as
extHostTypes
from
'
./extHostTypes
'
;
type
IconPath
=
URI
|
{
light
:
URI
,
dark
:
URI
};
class
ExtHostWebviewPanel
extends
Disposable
implements
vscode
.
WebviewPanel
{
readonly
#
handle
:
extHostProtocol
.
WebviewHandle
;
readonly
#
proxy
:
extHostProtocol
.
MainThreadWebviewPanelsShape
;
readonly
#
viewType
:
string
;
readonly
#
webview
:
ExtHostWebview
;
readonly
#
options
:
vscode
.
WebviewPanelOptions
;
#
title
:
string
;
#
iconPath
?:
IconPath
;
#
viewColumn
:
vscode
.
ViewColumn
|
undefined
=
undefined
;
#
visible
:
boolean
=
true
;
#
active
:
boolean
=
true
;
#
isDisposed
:
boolean
=
false
;
readonly
#
onDidDispose
=
this
.
_register
(
new
Emitter
<
void
>
());
public
readonly
onDidDispose
=
this
.
#
onDidDispose
.
event
;
readonly
#
onDidChangeViewState
=
this
.
_register
(
new
Emitter
<
vscode
.
WebviewPanelOnDidChangeViewStateEvent
>
());
public
readonly
onDidChangeViewState
=
this
.
#
onDidChangeViewState
.
event
;
constructor
(
handle
:
extHostProtocol
.
WebviewHandle
,
proxy
:
extHostProtocol
.
MainThreadWebviewPanelsShape
,
viewType
:
string
,
title
:
string
,
viewColumn
:
vscode
.
ViewColumn
|
undefined
,
editorOptions
:
vscode
.
WebviewPanelOptions
,
webview
:
ExtHostWebview
)
{
super
();
this
.
#
handle
=
handle
;
this
.
#
proxy
=
proxy
;
this
.
#
viewType
=
viewType
;
this
.
#
options
=
editorOptions
;
this
.
#
viewColumn
=
viewColumn
;
this
.
#
title
=
title
;
this
.
#
webview
=
webview
;
}
public
dispose
()
{
if
(
this
.
#
isDisposed
)
{
return
;
}
this
.
#
isDisposed
=
true
;
this
.
#
onDidDispose
.
fire
();
this
.
#
proxy
.
$disposeWebview
(
this
.
#
handle
);
this
.
#
webview
.
dispose
();
super
.
dispose
();
}
get
webview
()
{
this
.
assertNotDisposed
();
return
this
.
#
webview
;
}
get
viewType
():
string
{
this
.
assertNotDisposed
();
return
this
.
#
viewType
;
}
get
title
():
string
{
this
.
assertNotDisposed
();
return
this
.
#
title
;
}
set
title
(
value
:
string
)
{
this
.
assertNotDisposed
();
if
(
this
.
#
title
!==
value
)
{
this
.
#
title
=
value
;
this
.
#
proxy
.
$setTitle
(
this
.
#
handle
,
value
);
}
}
get
iconPath
():
IconPath
|
undefined
{
this
.
assertNotDisposed
();
return
this
.
#
iconPath
;
}
set
iconPath
(
value
:
IconPath
|
undefined
)
{
this
.
assertNotDisposed
();
if
(
this
.
#
iconPath
!==
value
)
{
this
.
#
iconPath
=
value
;
this
.
#
proxy
.
$setIconPath
(
this
.
#
handle
,
URI
.
isUri
(
value
)
?
{
light
:
value
,
dark
:
value
}
:
value
);
}
}
get
options
()
{
return
this
.
#
options
;
}
get
viewColumn
():
vscode
.
ViewColumn
|
undefined
{
this
.
assertNotDisposed
();
if
(
typeof
this
.
#
viewColumn
===
'
number
'
&&
this
.
#
viewColumn
<
0
)
{
// We are using a symbolic view column
// Return undefined instead to indicate that the real view column is currently unknown but will be resolved.
return
undefined
;
}
return
this
.
#
viewColumn
;
}
public
get
active
():
boolean
{
this
.
assertNotDisposed
();
return
this
.
#
active
;
}
public
get
visible
():
boolean
{
this
.
assertNotDisposed
();
return
this
.
#
visible
;
}
_updateViewState
(
newState
:
{
active
:
boolean
;
visible
:
boolean
;
viewColumn
:
vscode
.
ViewColumn
;
})
{
if
(
this
.
#
isDisposed
)
{
return
;
}
if
(
this
.
active
!==
newState
.
active
||
this
.
visible
!==
newState
.
visible
||
this
.
viewColumn
!==
newState
.
viewColumn
)
{
this
.
#
active
=
newState
.
active
;
this
.
#
visible
=
newState
.
visible
;
this
.
#
viewColumn
=
newState
.
viewColumn
;
this
.
#
onDidChangeViewState
.
fire
({
webviewPanel
:
this
});
}
}
public
reveal
(
viewColumn
?:
vscode
.
ViewColumn
,
preserveFocus
?:
boolean
):
void
{
this
.
assertNotDisposed
();
this
.
#
proxy
.
$reveal
(
this
.
#
handle
,
{
viewColumn
:
viewColumn
?
typeConverters
.
ViewColumn
.
from
(
viewColumn
)
:
undefined
,
preserveFocus
:
!!
preserveFocus
});
}
private
assertNotDisposed
()
{
if
(
this
.
#
isDisposed
)
{
throw
new
Error
(
'
Webview is disposed
'
);
}
}
}
export
class
ExtHostWebviewPanels
implements
extHostProtocol
.
ExtHostWebviewPanelsShape
{
private
static
newHandle
():
extHostProtocol
.
WebviewHandle
{
return
generateUuid
();
}
private
readonly
_proxy
:
extHostProtocol
.
MainThreadWebviewPanelsShape
;
private
readonly
_webviewPanels
=
new
Map
<
extHostProtocol
.
WebviewHandle
,
ExtHostWebviewPanel
>
();
private
readonly
_serializers
=
new
Map
<
string
,
{
readonly
serializer
:
vscode
.
WebviewPanelSerializer
;
readonly
extension
:
IExtensionDescription
;
}
>
();
constructor
(
mainContext
:
extHostProtocol
.
IMainContext
,
private
readonly
webviews
:
ExtHostWebviews
,
private
readonly
workspace
:
IExtHostWorkspace
|
undefined
,
)
{
this
.
_proxy
=
mainContext
.
getProxy
(
extHostProtocol
.
MainContext
.
MainThreadWebviewPanels
);
}
public
createWebviewPanel
(
extension
:
IExtensionDescription
,
viewType
:
string
,
title
:
string
,
showOptions
:
vscode
.
ViewColumn
|
{
viewColumn
:
vscode
.
ViewColumn
,
preserveFocus
?:
boolean
},
options
:
(
vscode
.
WebviewPanelOptions
&
vscode
.
WebviewOptions
)
=
{},
):
vscode
.
WebviewPanel
{
const
viewColumn
=
typeof
showOptions
===
'
object
'
?
showOptions
.
viewColumn
:
showOptions
;
const
webviewShowOptions
=
{
viewColumn
:
typeConverters
.
ViewColumn
.
from
(
viewColumn
),
preserveFocus
:
typeof
showOptions
===
'
object
'
&&
!!
showOptions
.
preserveFocus
};
const
handle
=
ExtHostWebviewPanels
.
newHandle
();
this
.
_proxy
.
$createWebviewPanel
(
toExtensionData
(
extension
),
handle
,
viewType
,
title
,
webviewShowOptions
,
convertWebviewOptions
(
extension
,
this
.
workspace
,
options
));
const
webview
=
this
.
webviews
.
createNewWebview
(
handle
,
options
,
extension
);
const
panel
=
this
.
createNewWebviewPanel
(
handle
,
viewType
,
title
,
viewColumn
,
options
,
webview
);
return
panel
;
}
public
$onDidChangeWebviewPanelViewStates
(
newStates
:
extHostProtocol
.
WebviewPanelViewStateData
):
void
{
const
handles
=
Object
.
keys
(
newStates
);
// Notify webviews of state changes in the following order:
// - Non-visible
// - Visible
// - Active
handles
.
sort
((
a
,
b
)
=>
{
const
stateA
=
newStates
[
a
];
const
stateB
=
newStates
[
b
];
if
(
stateA
.
active
)
{
return
1
;
}
if
(
stateB
.
active
)
{
return
-
1
;
}
return
(
+
stateA
.
visible
)
-
(
+
stateB
.
visible
);
});
for
(
const
handle
of
handles
)
{
const
panel
=
this
.
getWebviewPanel
(
handle
);
if
(
!
panel
)
{
continue
;
}
const
newState
=
newStates
[
handle
];
panel
.
_updateViewState
({
active
:
newState
.
active
,
visible
:
newState
.
visible
,
viewColumn
:
typeConverters
.
ViewColumn
.
to
(
newState
.
position
),
});
}
}
async
$onDidDisposeWebviewPanel
(
handle
:
extHostProtocol
.
WebviewHandle
):
Promise
<
void
>
{
const
panel
=
this
.
getWebviewPanel
(
handle
);
panel
?.
dispose
();
this
.
_webviewPanels
.
delete
(
handle
);
this
.
webviews
.
deleteWebview
(
handle
);
}
public
registerWebviewPanelSerializer
(
extension
:
IExtensionDescription
,
viewType
:
string
,
serializer
:
vscode
.
WebviewPanelSerializer
):
vscode
.
Disposable
{
if
(
this
.
_serializers
.
has
(
viewType
))
{
throw
new
Error
(
`Serializer for '
${
viewType
}
' already registered`
);
}
this
.
_serializers
.
set
(
viewType
,
{
serializer
,
extension
});
this
.
_proxy
.
$registerSerializer
(
viewType
);
return
new
extHostTypes
.
Disposable
(()
=>
{
this
.
_serializers
.
delete
(
viewType
);
this
.
_proxy
.
$unregisterSerializer
(
viewType
);
});
}
async
$deserializeWebviewPanel
(
webviewHandle
:
extHostProtocol
.
WebviewHandle
,
viewType
:
string
,
title
:
string
,
state
:
any
,
position
:
EditorViewColumn
,
options
:
modes
.
IWebviewOptions
&
modes
.
IWebviewPanelOptions
):
Promise
<
void
>
{
const
entry
=
this
.
_serializers
.
get
(
viewType
);
if
(
!
entry
)
{
throw
new
Error
(
`No serializer found for '
${
viewType
}
'`
);
}
const
{
serializer
,
extension
}
=
entry
;
const
webview
=
this
.
webviews
.
createNewWebview
(
webviewHandle
,
options
,
extension
);
const
revivedPanel
=
this
.
createNewWebviewPanel
(
webviewHandle
,
viewType
,
title
,
position
,
options
,
webview
);
await
serializer
.
deserializeWebviewPanel
(
revivedPanel
,
state
);
}
public
createNewWebviewPanel
(
webviewHandle
:
string
,
viewType
:
string
,
title
:
string
,
position
:
number
,
options
:
modes
.
IWebviewOptions
&
modes
.
IWebviewPanelOptions
,
webview
:
ExtHostWebview
)
{
const
panel
=
new
ExtHostWebviewPanel
(
webviewHandle
,
this
.
_proxy
,
viewType
,
title
,
typeof
position
===
'
number
'
&&
position
>=
0
?
typeConverters
.
ViewColumn
.
to
(
position
)
:
undefined
,
options
,
webview
);
this
.
_webviewPanels
.
set
(
webviewHandle
,
panel
);
return
panel
;
}
public
getWebviewPanel
(
handle
:
extHostProtocol
.
WebviewHandle
):
ExtHostWebviewPanel
|
undefined
{
return
this
.
_webviewPanels
.
get
(
handle
);
}
}
src/vs/workbench/test/browser/api/extHostWebview.test.ts
浏览文件 @
23fe7a39
...
...
@@ -13,6 +13,7 @@ import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import
{
NullApiDeprecationService
}
from
'
vs/workbench/api/common/extHostApiDeprecationService
'
;
import
{
IExtHostRpcService
}
from
'
vs/workbench/api/common/extHostRpcService
'
;
import
{
ExtHostWebviews
}
from
'
vs/workbench/api/common/extHostWebview
'
;
import
{
ExtHostWebviewPanels
}
from
'
vs/workbench/api/common/extHostWebviewPanels
'
;
import
{
EditorViewColumn
}
from
'
vs/workbench/api/common/shared/editor
'
;
import
type
*
as
vscode
from
'
vscode
'
;
import
{
SingleProxyRPCProtocol
}
from
'
./testRPCProtocol
'
;
...
...
@@ -35,6 +36,8 @@ suite('ExtHostWebview', () => {
isExtensionDevelopmentDebug
:
false
,
},
undefined
,
new
NullLogService
(),
NullApiDeprecationService
);
const
extHostWebviewPanels
=
new
ExtHostWebviewPanels
(
rpcProtocol
!
,
extHostWebviews
,
undefined
);
let
lastInvokedDeserializer
:
vscode
.
WebviewPanelSerializer
|
undefined
=
undefined
;
class
NoopSerializer
implements
vscode
.
WebviewPanelSerializer
{
...
...
@@ -48,20 +51,20 @@ suite('ExtHostWebview', () => {
const
serializerA
=
new
NoopSerializer
();
const
serializerB
=
new
NoopSerializer
();
const
serializerARegistration
=
extHostWebviews
.
registerWebviewPanelSerializer
(
extension
,
viewType
,
serializerA
);
const
serializerARegistration
=
extHostWebview
Panel
s
.
registerWebviewPanelSerializer
(
extension
,
viewType
,
serializerA
);
await
extHostWebviews
.
$deserializeWebviewPanel
(
'
x
'
,
viewType
,
'
title
'
,
{},
0
as
EditorViewColumn
,
{});
await
extHostWebview
Panel
s
.
$deserializeWebviewPanel
(
'
x
'
,
viewType
,
'
title
'
,
{},
0
as
EditorViewColumn
,
{});
assert
.
strictEqual
(
lastInvokedDeserializer
,
serializerA
);
assert
.
throws
(
()
=>
extHostWebviews
.
registerWebviewPanelSerializer
(
extension
,
viewType
,
serializerB
),
()
=>
extHostWebview
Panel
s
.
registerWebviewPanelSerializer
(
extension
,
viewType
,
serializerB
),
'
Should throw when registering two serializers for the same view
'
);
serializerARegistration
.
dispose
();
extHostWebviews
.
registerWebviewPanelSerializer
(
extension
,
viewType
,
serializerB
);
extHostWebview
Panel
s
.
registerWebviewPanelSerializer
(
extension
,
viewType
,
serializerB
);
await
extHostWebviews
.
$deserializeWebviewPanel
(
'
x
'
,
viewType
,
'
title
'
,
{},
0
as
EditorViewColumn
,
{});
await
extHostWebview
Panel
s
.
$deserializeWebviewPanel
(
'
x
'
,
viewType
,
'
title
'
,
{},
0
as
EditorViewColumn
,
{});
assert
.
strictEqual
(
lastInvokedDeserializer
,
serializerB
);
});
...
...
@@ -71,7 +74,10 @@ suite('ExtHostWebview', () => {
webviewResourceRoot
:
'
vscode-resource://{{resource}}
'
,
isExtensionDevelopmentDebug
:
false
,
},
undefined
,
new
NullLogService
(),
NullApiDeprecationService
);
const
webview
=
extHostWebviews
.
createWebviewPanel
({}
as
any
,
'
type
'
,
'
title
'
,
1
,
{});
const
extHostWebviewPanels
=
new
ExtHostWebviewPanels
(
rpcProtocol
!
,
extHostWebviews
,
undefined
);
const
webview
=
extHostWebviewPanels
.
createWebviewPanel
({}
as
any
,
'
type
'
,
'
title
'
,
1
,
{});
assert
.
strictEqual
(
webview
.
webview
.
asWebviewUri
(
URI
.
parse
(
'
file:///Users/codey/file.html
'
)).
toString
(),
...
...
@@ -110,7 +116,10 @@ suite('ExtHostWebview', () => {
webviewResourceRoot
:
`https://{{uuid}}.webview.contoso.com/commit/{{resource}}`
,
isExtensionDevelopmentDebug
:
false
,
},
undefined
,
new
NullLogService
(),
NullApiDeprecationService
);
const
webview
=
extHostWebviews
.
createWebviewPanel
({}
as
any
,
'
type
'
,
'
title
'
,
1
,
{});
const
extHostWebviewPanels
=
new
ExtHostWebviewPanels
(
rpcProtocol
!
,
extHostWebviews
,
undefined
);
const
webview
=
extHostWebviewPanels
.
createWebviewPanel
({}
as
any
,
'
type
'
,
'
title
'
,
1
,
{});
function
stripEndpointUuid
(
input
:
string
)
{
return
input
.
replace
(
/^https:
\/\/[^\.]
+
?\.
/
,
''
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录