Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
519ec86a
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
519ec86a
编写于
7月 02, 2019
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
swap web.resources with service worker approach
上级
7cbf591b
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
224 addition
and
212 deletion
+224
-212
resourceServiceWorkerMain.js
resourceServiceWorkerMain.js
+0
-40
src/vs/workbench/browser/web.main.ts
src/vs/workbench/browser/web.main.ts
+1
-5
src/vs/workbench/browser/web.resources.ts
src/vs/workbench/browser/web.resources.ts
+0
-124
src/vs/workbench/contrib/resources/browser/resourceServiceWorker.ts
...kbench/contrib/resources/browser/resourceServiceWorker.ts
+65
-2
src/vs/workbench/contrib/resources/browser/resourceServiceWorkerClient.ts
.../contrib/resources/browser/resourceServiceWorkerClient.ts
+130
-14
src/vs/workbench/contrib/resources/browser/resourceServiceWorkerMain.ts
...ch/contrib/resources/browser/resourceServiceWorkerMain.ts
+28
-27
未找到文件。
resourceServiceWorkerMain.js
已删除
100644 → 0
浏览文件 @
7cbf591b
"
use strict
"
;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
(
function
()
{
let
handler
;
self
.
addEventListener
(
'
fetch
'
,
event
=>
{
console
.
log
(
'
FETCH
'
,
event
);
if
(
handler
)
{
handler
.
handleFetchEvent
(
event
);
}
else
{
//@ts-ignore
event
.
respondWith
(
fetch
(
event
.
request
));
}
});
self
.
addEventListener
(
'
install
'
,
event
=>
{
let
loadPromise
=
new
Promise
((
resolve
,
reject
)
=>
{
// load loader
const
monacoBaseUrl
=
'
./out/
'
;
importScripts
(
monacoBaseUrl
+
'
vs/loader.js
'
);
require
.
config
({
baseUrl
:
monacoBaseUrl
,
catchError
:
true
});
require
([
'
vs/workbench/contrib/resources/browser/resourceServiceWorker
'
],
module
=>
{
handler
=
module
;
resolve
();
},
reject
);
});
//@ts-ignore
event
.
waitUntil
(
Promise
.
all
([
loadPromise
,
self
.
skipWaiting
()]));
});
self
.
addEventListener
(
'
activate
'
,
event
=>
{
//@ts-ignore
event
.
waitUntil
(
self
.
clients
.
claim
());
// Become available to all pages
});
})();
//# sourceMappingURL=resourceServiceWorkerMain.js.map
src/vs/workbench/browser/web.main.ts
浏览文件 @
519ec86a
...
...
@@ -29,7 +29,6 @@ import { URI } from 'vs/base/common/uri';
import
{
IWorkspaceInitializationPayload
}
from
'
vs/platform/workspaces/common/workspaces
'
;
import
{
WorkspaceService
}
from
'
vs/workbench/services/configuration/browser/configurationService
'
;
import
{
ConfigurationCache
}
from
'
vs/workbench/services/configuration/browser/configurationCache
'
;
import
{
WebResources
}
from
'
vs/workbench/browser/web.resources
'
;
import
{
ISignService
}
from
'
vs/platform/sign/common/sign
'
;
import
{
SignService
}
from
'
vs/platform/sign/browser/signService
'
;
import
{
hash
}
from
'
vs/base/common/hash
'
;
...
...
@@ -68,9 +67,6 @@ class CodeRendererMain extends Disposable {
// Layout
this
.
_register
(
addDisposableListener
(
window
,
EventType
.
RESIZE
,
()
=>
this
.
workbench
.
layout
()));
// Resource Loading
this
.
_register
(
new
WebResources
(
<
IFileService
>
services
.
serviceCollection
.
get
(
IFileService
)));
// Workbench Lifecycle
this
.
_register
(
this
.
workbench
.
onShutdown
(()
=>
this
.
dispose
()));
...
...
@@ -199,4 +195,4 @@ export function main(domElement: HTMLElement, options: IWorkbenchConstructionOpt
const
renderer
=
new
CodeRendererMain
(
domElement
,
options
);
return
renderer
.
open
();
}
\ No newline at end of file
}
src/vs/workbench/browser/web.resources.ts
已删除
100644 → 0
浏览文件 @
7cbf591b
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
getMediaMime
}
from
'
vs/base/common/mime
'
;
export
class
WebResources
{
private
readonly
_regexp
=
/url
\((
'|"
)?(
vscode-remote:
\/\/
.*
?)\1\)
/g
;
private
readonly
_urlCache
=
new
Map
<
string
,
string
>
();
private
readonly
_requestCache
=
new
Map
<
string
,
Promise
<
any
>>
();
private
readonly
_observer
:
MutationObserver
;
constructor
(@
IFileService
private
readonly
_fileService
:
IFileService
)
{
// todo@joh add observer to more than head-element
// todo@joh explore alternative approach
this
.
_observer
=
new
MutationObserver
(
r
=>
this
.
_handleMutation
(
r
));
this
.
_observer
.
observe
(
document
,
{
subtree
:
true
,
childList
:
true
,
attributes
:
true
,
attributeFilter
:
[
'
style
'
]
});
}
dispose
():
void
{
this
.
_observer
.
disconnect
();
this
.
_urlCache
.
forEach
(
value
=>
URL
.
revokeObjectURL
(
value
));
}
private
_handleMutation
(
records
:
MutationRecord
[]):
void
{
for
(
const
record
of
records
)
{
if
(
record
.
target
.
nodeName
===
'
STYLE
'
)
{
// style-element directly modified
this
.
_handleStyleNode
(
record
.
target
);
}
else
if
(
record
.
target
.
nodeName
===
'
HEAD
'
&&
record
.
type
===
'
childList
'
)
{
// style-element added to head
record
.
addedNodes
.
forEach
(
node
=>
{
if
(
node
.
nodeName
===
'
STYLE
'
)
{
this
.
_handleStyleNode
(
node
);
}
});
}
else
if
(
record
.
type
===
'
attributes
'
)
{
// style-attribute
this
.
_handleAttrMutation
(
record
.
target
);
}
}
}
private
_handleStyleNode
(
target
:
Node
):
void
{
if
(
target
.
textContent
&&
target
.
textContent
.
indexOf
(
'
vscode-remote://
'
)
>=
0
)
{
const
content
=
target
.
textContent
;
this
.
_rewriteUrls
(
content
).
then
(
value
=>
{
if
(
content
===
target
.
textContent
)
{
target
.
textContent
=
value
;
}
}).
catch
(
e
=>
{
console
.
error
(
e
);
});
}
}
private
_handleAttrMutation
(
target
:
Node
):
void
{
const
styleValue
=
(
<
HTMLElement
>
target
).
getAttribute
(
'
style
'
);
if
(
styleValue
&&
styleValue
.
indexOf
(
'
vscode-remote://
'
)
>=
0
)
{
this
.
_rewriteUrls
(
styleValue
).
then
(
value
=>
{
if
(
value
!==
styleValue
)
{
(
<
HTMLElement
>
target
).
setAttribute
(
'
style
'
,
value
);
}
}).
catch
(
e
=>
{
console
.
error
(
e
);
});
}
}
private
async
_rewriteUrls
(
textContent
:
string
):
Promise
<
string
>
{
return
textContent
.
replace
(
/url
\((
'|"
)?(
vscode-remote:
\/\/(
.*
?))\1\)
/ig
,
function
(
_m
,
quote
,
url
)
{
return
`url("http://localhost:9888/out/vs/workbench/contrib/resources/browser/foo?
${
encodeURIComponent
(
url
)}
")`
;
// return `url(${quote}${location.href}out/vs/workbench/contrib/resources/browser/?${encodeURIComponent(url)}${quote})`;
});
}
private
async
_rewriteUrls2
(
textContent
:
string
):
Promise
<
string
>
{
const
positions
:
number
[]
=
[];
const
promises
:
Promise
<
any
>
[]
=
[];
let
match
:
RegExpMatchArray
|
null
=
null
;
while
(
match
=
this
.
_regexp
.
exec
(
textContent
))
{
const
remoteUrl
=
match
[
2
];
positions
.
push
(
match
.
index
!
+
'
url(
'
.
length
+
(
typeof
match
[
1
]
===
'
string
'
?
match
[
1
].
length
:
0
));
positions
.
push
(
remoteUrl
.
length
);
if
(
!
this
.
_urlCache
.
has
(
remoteUrl
))
{
let
request
=
this
.
_requestCache
.
get
(
remoteUrl
);
if
(
!
request
)
{
const
uri
=
URI
.
parse
(
remoteUrl
,
true
);
request
=
this
.
_fileService
.
readFile
(
uri
).
then
(
file
=>
{
const
blobUrl
=
URL
.
createObjectURL
(
new
Blob
([
file
.
value
.
buffer
],
{
type
:
getMediaMime
(
uri
.
path
)
}));
this
.
_urlCache
.
set
(
remoteUrl
,
blobUrl
);
});
this
.
_requestCache
.
set
(
remoteUrl
,
request
);
}
promises
.
push
(
request
);
}
}
let
content
=
textContent
;
await
Promise
.
all
(
promises
);
for
(
let
i
=
positions
.
length
-
1
;
i
>=
0
;
i
-=
2
)
{
const
start
=
positions
[
i
-
1
];
const
len
=
positions
[
i
];
const
url
=
this
.
_urlCache
.
get
(
content
.
substr
(
start
,
len
));
content
=
content
.
substring
(
0
,
start
)
+
url
+
content
.
substring
(
start
+
len
);
}
return
content
;
}
}
src/vs/workbench/contrib/resources/browser/resourceServiceWorker.ts
浏览文件 @
519ec86a
...
...
@@ -3,9 +3,72 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
generateUuid
}
from
'
vs/base/common/uuid
'
;
import
{
getMediaMime
}
from
'
vs/base/common/mime
'
;
export
function
handleFetchEvent
(
event
)
{
const
cacheName
=
'
vscode-resources
'
;
console
.
log
(
'
FETCH
'
,
event
);
declare
const
clients
:
{
get
(
s
:
string
):
Promise
<
any
>
};
const
_pending
=
new
Map
<
string
,
Function
>
();
export
function
handleMessageEvent
(
event
:
MessageEvent
):
void
{
const
fn
=
_pending
.
get
(
event
.
data
.
token
);
if
(
fn
)
{
fn
(
event
.
data
.
data
);
_pending
.
delete
(
event
.
data
.
token
);
}
}
export
async
function
handleFetchEvent
(
event
:
any
):
Promise
<
Response
|
undefined
>
{
const
url
=
URI
.
parse
(
event
.
request
.
url
);
if
(
url
.
path
!==
'
/vscode-resources/fetch
'
)
{
return
undefined
;
}
if
(
!
event
.
clientId
)
{
return
undefined
;
}
const
cachedValue
=
await
caches
.
open
(
cacheName
).
then
(
cache
=>
cache
.
match
(
event
.
request
));
if
(
cachedValue
)
{
return
cachedValue
;
}
// console.log('fetch', url.query);
try
{
const
token
=
generateUuid
();
return
new
Promise
<
Response
>
(
async
resolve
=>
{
const
handle
=
setTimeout
(()
=>
{
resolve
(
new
Response
(
undefined
,
{
status
:
500
,
statusText
:
'
timeout
'
}));
_pending
.
delete
(
token
);
},
5000
);
_pending
.
set
(
token
,
(
data
:
ArrayBuffer
)
=>
{
clearTimeout
(
handle
);
const
res
=
new
Response
(
data
,
{
status
:
200
,
headers
:
{
'
Content-Type
'
:
getMediaMime
(
URI
.
parse
(
url
.
query
).
path
)
||
'
text/plain
'
}
});
caches
.
open
(
cacheName
).
then
(
cache
=>
{
cache
.
put
(
event
.
request
,
res
.
clone
());
resolve
(
res
);
});
});
const
client
=
await
clients
.
get
(
event
.
clientId
);
client
.
postMessage
({
uri
:
url
.
query
,
token
});
});
}
catch
(
err
)
{
console
.
error
(
err
);
return
new
Response
(
err
,
{
status
:
500
});
}
}
src/vs/workbench/contrib/resources/browser/resourceServiceWorkerClient.ts
浏览文件 @
519ec86a
...
...
@@ -4,26 +4,142 @@
*--------------------------------------------------------------------------------------------*/
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
DisposableStore
,
toDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
Registry
}
from
'
vs/platform/registry/common/platform
'
;
import
{
IWorkbenchContributionsRegistry
,
Extensions
}
from
'
vs/workbench/common/contributions
'
;
import
{
LifecyclePhase
}
from
'
vs/platform/lifecycle/common/lifecycle
'
;
export
class
ResourceServiceWorkerService
{
// todo@joh explore alternative, explicit approach
class
ResourcesMutationObserver
{
private
readonly
_urlCache
=
new
Map
<
string
,
string
>
();
private
readonly
_observer
:
MutationObserver
;
private
readonly
_regexp
=
/url
\((
'|"
)?(
vscode-remote:
\/\/(
.*
?))\1\)
/ig
;
constructor
()
{
this
.
_observer
=
new
MutationObserver
(
r
=>
this
.
_handleMutation
(
r
));
this
.
_observer
.
observe
(
document
,
{
subtree
:
true
,
childList
:
true
,
attributes
:
true
,
attributeFilter
:
[
'
style
'
]
});
this
.
scan
();
}
scan
():
void
{
document
.
querySelectorAll
(
'
style
'
).
forEach
(
value
=>
this
.
_handleStyleNode
(
value
));
// todo@joh more!
}
dispose
():
void
{
this
.
_observer
.
disconnect
();
this
.
_urlCache
.
forEach
(
value
=>
URL
.
revokeObjectURL
(
value
));
}
private
_handleMutation
(
records
:
MutationRecord
[]):
void
{
for
(
const
record
of
records
)
{
if
(
record
.
target
.
nodeName
===
'
STYLE
'
)
{
// style-element directly modified
this
.
_handleStyleNode
(
record
.
target
);
}
else
if
(
record
.
target
.
nodeName
===
'
HEAD
'
&&
record
.
type
===
'
childList
'
)
{
// style-element added to head
record
.
addedNodes
.
forEach
(
node
=>
{
if
(
node
.
nodeName
===
'
STYLE
'
)
{
this
.
_handleStyleNode
(
node
);
}
});
}
else
if
(
record
.
type
===
'
attributes
'
)
{
// style-attribute
this
.
_handleAttrMutation
(
record
.
target
);
}
}
}
private
_handleStyleNode
(
target
:
Node
):
void
{
if
(
target
.
textContent
&&
target
.
textContent
.
indexOf
(
'
vscode-remote://
'
)
>=
0
)
{
const
content
=
target
.
textContent
;
this
.
_rewriteUrls
(
content
).
then
(
value
=>
{
if
(
content
===
target
.
textContent
)
{
target
.
textContent
=
value
;
}
}).
catch
(
e
=>
{
console
.
error
(
e
);
});
}
}
private
_handleAttrMutation
(
target
:
Node
):
void
{
const
styleValue
=
(
<
HTMLElement
>
target
).
getAttribute
(
'
style
'
);
if
(
styleValue
&&
styleValue
.
indexOf
(
'
vscode-remote://
'
)
>=
0
)
{
this
.
_rewriteUrls
(
styleValue
).
then
(
value
=>
{
if
(
value
!==
styleValue
)
{
(
<
HTMLElement
>
target
).
setAttribute
(
'
style
'
,
value
);
}
}).
catch
(
e
=>
{
console
.
error
(
e
);
});
}
}
private
async
_rewriteUrls
(
textContent
:
string
):
Promise
<
string
>
{
return
textContent
.
replace
(
this
.
_regexp
,
function
(
_m
,
quote
,
url
)
{
return
`url(
${
quote
}${
location
.
href
}
vscode-resources/fetch?
${
encodeURIComponent
(
url
)}${
quote
}
)`
;
});
}
}
class
ResourceServiceWorker
{
private
readonly
_disposables
=
new
DisposableStore
();
constructor
(
@
IFileService
private
readonly
_fileService
:
IFileService
,
)
{
console
.
log
(
this
.
_fileService
);
this
.
_initServiceWorker
();
this
.
_initFetchHandler
();
}
dispose
():
void
{
this
.
_disposables
.
dispose
();
}
private
_initServiceWorker
():
void
{
const
url
=
'
./resourceServiceWorkerMain.js
'
;
navigator
.
serviceWorker
.
register
(
url
).
then
(()
=>
{
// console.log('registered');
return
navigator
.
serviceWorker
.
ready
;
}).
then
(()
=>
{
// console.log('ready');
this
.
_disposables
.
add
(
new
ResourcesMutationObserver
());
}).
catch
(
err
=>
{
console
.
error
(
err
);
});
}
private
_initFetchHandler
():
void
{
const
fetchListener
:
(
this
:
ServiceWorkerContainer
,
ev
:
MessageEvent
)
=>
void
=
event
=>
{
const
uri
=
URI
.
parse
(
event
.
data
.
uri
);
this
.
_fileService
.
readFile
(
uri
).
then
(
file
=>
{
// todo@joh typings
(
<
any
>
event
.
source
).
postMessage
({
token
:
event
.
data
.
token
,
data
:
file
.
value
.
buffer
.
buffer
},
[
file
.
value
.
buffer
.
buffer
]);
});
};
navigator
.
serviceWorker
.
addEventListener
(
'
message
'
,
fetchListener
);
this
.
_disposables
.
add
(
toDisposable
(()
=>
navigator
.
serviceWorker
.
removeEventListener
(
'
message
'
,
fetchListener
)));
}
}
// const url = require.toUrl('./resourceServiceWorkerMain.js');
const
url
=
'
./resourceServiceWorkerMain.js
'
;
navigator
.
serviceWorker
.
register
(
url
,
// { scope: './out/vs/workbench/contrib/resources/browser/' }
).
then
(
value
=>
{
console
.
log
(
value
);
console
.
log
(
navigator
.
serviceWorker
.
controller
);
}).
catch
(
err
=>
{
console
.
error
(
err
);
});
Registry
.
as
<
IWorkbenchContributionsRegistry
>
(
Extensions
.
Workbench
).
registerWorkbenchContribution
(
ResourceServiceWorker
,
LifecyclePhase
.
Starting
);
src/vs/workbench/contrib/resources/browser/resourceServiceWorkerMain.ts
浏览文件 @
519ec86a
...
...
@@ -4,41 +4,42 @@
*--------------------------------------------------------------------------------------------*/
(
function
()
{
type
Handler
=
{
handleFetchEvent
(
event
:
Event
):
void
;
handleFetchEvent
(
event
:
Event
):
Promise
<
Response
|
undefined
>
;
handleMessageEvent
(
event
:
MessageEvent
):
void
;
};
let
handler
:
Handler
|
undefined
;
self
.
addEventListener
(
'
fetch
'
,
event
=>
{
console
.
log
(
'
FETCH
'
,
event
);
if
(
handler
)
{
handler
.
handleFetchEvent
(
event
);
}
else
{
//@ts-ignore
event
.
respondWith
(
fetch
(
event
.
request
));
}
const
handlerPromise
=
new
Promise
<
Handler
>
((
resolve
,
reject
)
=>
{
// load loader
const
baseUrl
=
'
./out/
'
;
importScripts
(
baseUrl
+
'
vs/loader.js
'
);
require
.
config
({
baseUrl
,
catchError
:
true
});
require
([
'
vs/workbench/contrib/resources/browser/resourceServiceWorker
'
],
resolve
,
reject
);
});
self
.
addEventListener
(
'
install
'
,
event
=>
{
let
loadPromise
=
new
Promise
((
resolve
,
reject
)
=>
{
// load loader
const
monacoBaseUrl
=
'
../../../../../
'
;
importScripts
(
monacoBaseUrl
+
'
vs/loader.js
'
);
require
.
config
({
baseUrl
:
monacoBaseUrl
,
catchError
:
true
});
require
([
'
vs/workbench/contrib/resources/browser/resourceServiceWorker
'
],
module
=>
{
handler
=
module
;
resolve
();
},
reject
);
self
.
addEventListener
(
'
message
'
,
event
=>
{
handlerPromise
.
then
(
handler
=>
{
handler
.
handleMessageEvent
(
event
);
});
});
self
.
addEventListener
(
'
fetch
'
,
(
event
:
any
)
=>
{
event
.
respondWith
(
handlerPromise
.
then
(
handler
=>
{
return
handler
.
handleFetchEvent
(
event
).
then
(
value
=>
{
if
(
value
instanceof
Response
)
{
return
value
;
}
else
{
return
fetch
(
event
.
request
);
}
});
}));
});
self
.
addEventListener
(
'
install
'
,
event
=>
{
//@ts-ignore
event
.
waitUntil
(
Promise
.
all
([
loadPromise
,
self
.
skipWaiting
()]
));
event
.
waitUntil
(
self
.
skipWaiting
(
));
});
self
.
addEventListener
(
'
activate
'
,
event
=>
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录