1 Star 0 Fork 0

冰原狼/kankanolss

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
serviceworker.js 13.33 KB
一键复制 编辑 原始数据 按行查看 历史
kankanol 提交于 2022-03-17 18:34 . init
var DisconnectResponse;
(function (DisconnectResponse) {
DisconnectResponse[DisconnectResponse["Disconnected"] = 0] = "Disconnected";
DisconnectResponse[DisconnectResponse["Waiting"] = 1] = "Waiting";
DisconnectResponse[DisconnectResponse["TimedOut"] = 2] = "TimedOut";
})(DisconnectResponse || (DisconnectResponse = {}));
initWebappServiceWorker();
initWebUSB();
function initWebappServiceWorker() {
// Empty string for released, otherwise contains the ref or version path
const ref = `@relprefix@`.replace("---", "").replace(/^\//, "");
// We don't do offline for version paths, only named releases
const isNamedEndpoint = ref.indexOf("/") === -1;
// pxtRelId is replaced with the commit hash for this release
const refCacheName = "makecode;" + ref + ";@pxtRelId@";
const cdnUrl = `@cdnUrl@`;
const webappUrls = [
// The current page
`@targetUrl@/` + ref,
`@simUrl@`,
// webapp files
`/semantic.js`,
`/main.js`,
`/pxtapp.js`,
`/typescript.js`,
`/marked/marked.min.js`,
`/highlight.js/highlight.pack.js`,
`/jquery.js`,
`/pxtlib.js`,
`/pxtcompiler.js`,
`/pxtpy.js`,
`/pxtblockly.js`,
`/pxtwinrt.js`,
`/pxteditor.js`,
`/pxtsim.js`,
`/pxtembed.js`,
`/pxtworker.js`,
`/pxtweb.js`,
`/blockly.css`,
`/semantic.css`,
`/rtlsemantic.css`,
// blockly
`/blockly/media/sprites.png`,
`/blockly/media/click.mp3`,
`/blockly/media/disconnect.wav`,
`/blockly/media/delete.mp3`,
// monaco; keep in sync with webapp/public/index.html
`/vs/loader.js`,
`/vs/base/worker/workerMain.js`,
`/vs/basic-languages/bat/bat.js`,
`/vs/basic-languages/cpp/cpp.js`,
`/vs/basic-languages/python/python.js`,
`/vs/basic-languages/markdown/markdown.js`,
`/vs/editor/editor.main.css`,
`/vs/editor/editor.main.js`,
`/vs/editor/editor.main.nls.js`,
`/vs/language/json/jsonMode.js`,
`/vs/language/json/jsonWorker.js`,
// charts
`/smoothie/smoothie_compressed.js`,
`/images/Bars_black.gif`,
// gifjs
`/gifjs/gif.js`,
// ai
`/ai.0.js`,
// target
`/target.js`,
// These macros should be replaced by the backend
`/fieldeditors.js`,
`/editor.js`,
``,
`@targetUrl@/monacoworker.js`,
`@targetUrl@/worker.js`
];
// Replaced by the backend by a list of encoded urls separated by semicolons
const cachedHexFiles = decodeURLs(``);
const cachedTargetImages = decodeURLs(`%2Fdocs%5Cstatic%5Clogo.portrait.white.svg;%2Fdocs%5Cstatic%5Clogo.square.white.svg;%2Fdocs%5Cstatic%5Clogo.square.white.svg;%2Fdocs%5Cstatic%5Clogo.portrait.black.svg;%2Fdocs%5Cstatic%5Cicons%5Capple-touch-icon.png;%2Fdocs%5Cstatic%5Cicons%5Capple-touch-icon.png;%2Fdocs%5Cstatic%5CMicrosoft_logo_rgb_W-white_D-square.png;%2Fdocs%5Cstatic%5CMicrosoft_logo_rgb_W-white_D.png`);
// Duplicate entries in this list will cause an exception so call dedupe
// just in case
const allFiles = dedupe(webappUrls.concat(cachedTargetImages)
.map(url => url.trim())
.filter(url => !!url && url.indexOf("@") !== 0));
let didInstall = false;
self.addEventListener("install", (ev) => {
if (!isNamedEndpoint) {
console.log("Skipping service worker install for unnamed endpoint");
return;
}
didInstall = true;
console.log("Installing service worker...");
ev.waitUntil(caches.open(refCacheName)
.then(cache => {
console.log("Opened cache");
console.log("Caching:\n" + allFiles.join("\n"));
return cache.addAll(allFiles).then(() => cache);
})
.then(cache => cache.addAll(cachedHexFiles).catch(e => {
// Hex files might return a 404 if they haven't hit the backend yet. We
// need to catch the exception or the service worker will fail to install
console.log("Failed to cache hexfiles");
}))
.then(() => self.skipWaiting()));
});
self.addEventListener("activate", (ev) => {
if (!isNamedEndpoint) {
console.log("Skipping service worker activate for unnamed endpoint");
return;
}
console.log("Activating service worker...");
ev.waitUntil(caches.keys()
.then(cacheNames => {
// Delete all caches that "belong" to this ref except for the current version
const toDelete = cacheNames.filter(c => {
const cacheRef = getRefFromCacheName(c);
return cacheRef === null || (cacheRef === ref && c !== refCacheName);
});
return Promise.all(toDelete.map(name => caches.delete(name)));
})
.then(() => {
if (didInstall) {
// Only notify clients for the first activation
didInstall = false;
return notifyAllClientsAsync();
}
return Promise.resolve();
}));
});
self.addEventListener("fetch", (ev) => {
ev.respondWith(caches.match(ev.request)
.then(response => {
return response || fetch(ev.request);
}));
});
function dedupe(urls) {
const res = [];
for (const url of urls) {
if (res.indexOf(url) === -1)
res.push(url);
}
return res;
}
function getRefFromCacheName(name) {
const parts = name.split(";");
if (parts.length !== 3)
return null;
return parts[1];
}
function decodeURLs(encodedURLs) {
// Charcode 64 is '@', we need to calculate it because otherwise the minifier
// will combine the string concatenation into @cdnUrl@ and get mangled by the backend
const cdnEscaped = String.fromCharCode(64) + "cdnUrl" + String.fromCharCode(64);
return dedupe(encodedURLs.split(";")
.map(encoded => decodeURIComponent(encoded).replace(cdnEscaped, cdnUrl).trim()));
}
function notifyAllClientsAsync() {
const scope = self;
return scope.clients.claim().then(() => scope.clients.matchAll()).then(clients => {
clients.forEach(client => client.postMessage({
type: "serviceworker",
state: "activated",
ref: ref
}));
});
}
}
// The ServiceWorker manages the webUSB sharing between tabs/windows in the browser. Only
// one client can connect to webUSB at a time
function initWebUSB() {
// Webusb doesn't love it when we connect/reconnect too quickly
const minimumLockWaitTime = 4000;
// The ID of the client who currently has the lock on webUSB
let lockGranted;
let lastLockTime = 0;
let waitingLock;
let state = "idle";
let pendingDisconnectResolver;
let statusResolver;
self.addEventListener("message", async (ev) => {
const message = ev.data;
if ((message === null || message === void 0 ? void 0 : message.type) === "serviceworkerclient") {
if (message.action === "request-packet-io-lock") {
if (!lockGranted)
lockGranted = await checkForExistingLockAsync();
// Deny the lock if we are in the process of granting it to someone else
if (state === "granting") {
await sendToAllClientsAsync({
type: "serviceworker",
action: "packet-io-lock-granted",
granted: false,
lock: message.lock
});
return;
}
console.log("Received lock request " + message.lock);
// Throttle reconnect requests
const timeSinceLastLock = Date.now() - lastLockTime;
waitingLock = message.lock;
if (timeSinceLastLock < minimumLockWaitTime) {
state = "waiting";
console.log("Waiting to grant lock request " + message.lock);
await delay(minimumLockWaitTime - timeSinceLastLock);
}
// We received a more recent request while we were waiting, so abandon this one
if (waitingLock !== message.lock) {
console.log("Rejecting old lock request " + message.lock);
await sendToAllClientsAsync({
type: "serviceworker",
action: "packet-io-lock-granted",
granted: false,
lock: message.lock
});
return;
}
state = "granting";
// First we need to tell whoever currently has the lock to disconnect
// and poll until they have finished
if (lockGranted) {
let resp;
do {
console.log("Sending disconnect request " + message.lock);
resp = await waitForLockDisconnectAsync();
if (resp === DisconnectResponse.Waiting) {
console.log("Waiting on disconnect request " + message.lock);
await delay(1000);
}
} while (resp === DisconnectResponse.Waiting);
}
// Now we can notify that the request has been granted
console.log("Granted lock request " + message.lock);
lockGranted = message.lock;
await sendToAllClientsAsync({
type: "serviceworker",
action: "packet-io-lock-granted",
granted: true,
lock: message.lock
});
lastLockTime = Date.now();
state = "idle";
}
else if (message.action === "release-packet-io-lock") {
// The client released the webusb lock for some reason (e.g. went to home screen)
console.log("Received disconnect for " + lockGranted);
lockGranted = undefined;
if (pendingDisconnectResolver)
pendingDisconnectResolver(DisconnectResponse.Disconnected);
}
else if (message.action === "packet-io-lock-disconnect") {
// Response to a disconnect request we sent
console.log("Received disconnect response for " + lockGranted);
if (message.didDisconnect)
lockGranted = undefined;
if (pendingDisconnectResolver)
pendingDisconnectResolver(message.didDisconnect ? DisconnectResponse.Disconnected : DisconnectResponse.Waiting);
}
else if (message.action === "packet-io-supported") {
await sendToAllClientsAsync({
type: "serviceworker",
action: "packet-io-supported",
supported: true
});
}
else if (message.action === "packet-io-status" && message.hasLock && statusResolver) {
statusResolver(message.lock);
}
}
});
async function sendToAllClientsAsync(message) {
const clients = await self.clients.matchAll();
clients.forEach(c => c.postMessage(message));
}
// Waits for the disconnect and times-out after 5 seconds if there is no response
function waitForLockDisconnectAsync() {
let ref;
const promise = new Promise((resolve) => {
console.log("Waiting for disconnect " + lockGranted);
pendingDisconnectResolver = resolve;
sendToAllClientsAsync({
type: "serviceworker",
action: "packet-io-lock-disconnect",
lock: lockGranted
});
});
const timeoutPromise = new Promise(resolve => {
ref = setTimeout(() => {
console.log("Timed-out disconnect request " + lockGranted);
resolve(DisconnectResponse.TimedOut);
}, 5000);
});
return Promise.race([promise, timeoutPromise])
.then(resp => {
clearTimeout(ref);
pendingDisconnectResolver = undefined;
return resp;
});
}
function checkForExistingLockAsync() {
if (lockGranted)
return Promise.resolve(lockGranted);
let ref;
const promise = new Promise(resolve => {
console.log("check for existing lock");
statusResolver = resolve;
sendToAllClientsAsync({
type: "serviceworker",
action: "packet-io-status"
});
});
const timeoutPromise = new Promise(resolve => {
ref = setTimeout(() => {
console.log("Timed-out check for existing lock");
resolve(undefined);
}, 1000);
});
return Promise.race([promise, timeoutPromise])
.then(resp => {
clearTimeout(ref);
statusResolver = undefined;
return resp;
});
}
function delay(millis) {
return new Promise(resolve => {
setTimeout(resolve, millis);
});
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/kankanol/kankanolss.git
git@gitee.com:kankanol/kankanolss.git
kankanol
kankanolss
kankanolss
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385