Skip to content

Commit

Permalink
refactor(runtime,api): more progress towards supporting multiple origins
Browse files Browse the repository at this point in the history
  • Loading branch information
jwerle committed Jan 4, 2025
1 parent 255c341 commit 863b4b2
Show file tree
Hide file tree
Showing 138 changed files with 6,052 additions and 5,201 deletions.
8 changes: 5 additions & 3 deletions api/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function serializeConfig (config) {
export { client, menu }

// get this from constant value in runtime
export const MAX_WINDOWS = 32
export const MAX_WINDOWS = 64

export class ApplicationWindowList {
#list = []
Expand Down Expand Up @@ -88,8 +88,8 @@ export class ApplicationWindowList {
return this.length
}

get [Symbol.iterator] () {
return this.#list[Symbol.iterator]
[Symbol.iterator] () {
return this.#list[Symbol.iterator]()
}

forEach (callback, thisArg) {
Expand Down Expand Up @@ -267,6 +267,8 @@ export async function createWindow (opts) {
resourcesDirectory: opts.resourcesDirectory ?? '',
shouldExitApplicationOnClose: opts.shouldExitApplicationOnClose ?? false,
shouldPreferServiceWorker: Boolean(opts.shouldPreferServiceWorker ?? false),
// @ts-ignore
reserved: Boolean(opts.reserved),
/**
* @private
* @type {number}
Expand Down
24 changes: 19 additions & 5 deletions api/ipc.js
Original file line number Diff line number Diff line change
Expand Up @@ -1147,6 +1147,7 @@ export function sendSync (command, value = '', options = null, buffer = null) {

let response = null
try {
console.log({ uri })
response = globalThis.__global_ipc_extension_handler(uri)
} catch (err) {
return Result.from(null, err)
Expand Down Expand Up @@ -1778,6 +1779,18 @@ export function findIPCMessageTransfers (transfers, object) {
)
) {
const port = IPCMessagePort.create(object)
object.addEventListener('message', function onMessage (event) {
if (port.closed === true) {
port.onmessage = null
event.preventDefault()
event.stopImmediatePropagation()
object.removeEventListener('message', onMessage)
return false
}

port.dispatchEvent(new MessageEvent('message', event))
})


port.onmessage = (event) => {
if (port.closed === true) {
Expand Down Expand Up @@ -2067,19 +2080,20 @@ export class IPCMessageChannel extends MessageChannel {
constructor (options = null) {
super()
this.#id = String(options?.id ?? rand64())
this.#channel = options?.channel ?? new IPCBroadcastChannel(this.#id)
this.#channel = options?.channel ?? new BroadcastChannel(this.#id)

this.#port1 = IPCMessagePort.create(options?.port1)
this.#port2 = IPCMessagePort.create(options?.port2)

this.port1[Symbol.for('socket.runtime.ipc.MessagePort.handlePostMessage')] = (message, options) => {
this.port2.postMessage(message, options)
this.port2.channel.postMessage(message, options)
return false
}

this.port2.addEventListener('message', (e) => {
this.port1.postMessage(e.data)
})
this.port2[Symbol.for('socket.runtime.ipc.MessagePort.handlePostMessage')] = (message, options) => {
this.port2.channel.postMessage(message, options)
return false
}
}

get id () {
Expand Down
2 changes: 1 addition & 1 deletion api/process/signal.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import os from '../os.js'

export { constants }

export const channel = new ipc.IPCBroadcastChannel('socket.runtime.signal')
export const channel = new BroadcastChannel('socket.runtime.signal')

export const SIGHUP = constants.SIGHUP
export const SIGINT = constants.SIGINT
Expand Down
2 changes: 1 addition & 1 deletion api/service-worker/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ServiceWorkerContainerInternalState {
currentWindow = null
controller = null
sharedWorker = null
channel = new ipc.IPCBroadcastChannel('socket.runtime.ServiceWorkerContainer')
channel = new BroadcastChannel('socket.runtime.ServiceWorkerContainer')
ready = new Deferred()
init = new Deferred()

Expand Down
115 changes: 108 additions & 7 deletions api/service-worker/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,124 @@
value: true
})
</script>
<script type="module" src="./main.js"></script>
<script type="module">
import application from 'socket:application'
import process from 'socket:process'

Object.assign(globalThis, {
async openExternalLink (href) {
const currentWindow = await application.getCurrentWindow()
await currentWindow.openExternal(href)
}
})

document.title = `Service Worker Debugger - v${process.version}`
</script>
<script type="module" src="./init.js"></script>
<style type="text/css" media="all">
* {
box-sizing: border-box;
}

body {
display: flex;
width: 100%;
background: rgba(40, 40, 40, 1);
color: rgba(255, 255, 255, 1);
font-family: 'Inter-Light', sans-serif;
font-size: 14px;
margin: 0;
padding: 0;
position: absolute; top: 0px; left: 0; right:0; bottom: 0px;
}

iframe {
border: none;
a {
color: inherit;
text-decoration: none;
transition: all 0.2s ease;

&.with-hover:hover {
border-bottom: 2px solid rgba(255, 255, 255, 1);
}
}

p {
background: rgba(14, 85, 152, .25);
border-radius: 2px;
display: inline-block;
font: 12px/26px 'Inter-Light', sans-serif;
margin: 0;
text-align: center;
width: 100%;
height: 100vh;

&.message {
display: block;
overflow: hidden;
padding: 0 8px;
position: relative;
text-overflow: ellipsis;
white-space: nowrap;
width: 100%;
}
}

pre#log {
background: rgba(0, 0, 0, 1);
overflow-y: scroll;
padding: 16px;
margin: 0;
position: absolute; top: 0px; left: 0; right:0; bottom: 0px;

& span {
opacity: 0.8;
transition: all 0.2s ease;

&:hover {
opacity: 1;
transition: all 0.05s ease;
}

& code {
color: rgb(215, 215, 215);
display: block;
font-size: 12px;
line-break: anywhere;
margin-bottom: 8px;
opacity: 0.8;
white-space: wrap;
transition: all 0.1s ease;

&:hover {
color: rgb(225, 225, 225);
opacity: 1;
transition: all 0.025s ease;
}

& span {
&.red {
color: red;
}
}
}

& details {
&[open] span {
opacity: 1;
transition: all 0.05s ease;
& code {
color: rgb(225, 225, 225);
opacity: 1;
transition: all 0.025s ease;
}
}

& > summary {
cursor: pointer;
list-style: none;
}
}
}
}
</style>
</head>
<body>
<pre id="log"></pre>
</body>
</html>
50 changes: 31 additions & 19 deletions api/service-worker/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { Notification } from '../notification.js'
import { sleep } from '../timers.js'
import globals from '../internal/globals.js'
import crypto from '../crypto.js'
import hooks from '../hooks.js'
import ipc from '../ipc.js'

export const workers = new Map()
export const channel = new ipc.IPCBroadcastChannel('socket.runtime.serviceWorker')

globals.register('ServiceWorkerContext.workers', workers)
globals.register('ServiceWorkerContext.info', new Map())
Expand All @@ -24,7 +24,7 @@ sharedWorker.port.onmessage = (event) => {
}
}
} else if (event.data?.showNotification && event.data.registration?.id) {
onShowNotification(event, sharedWorker.port)
onNotificationShow(event, sharedWorker.port)
} else if (event.data?.getNotifications && event.data.registration?.id) {
onGetNotifications(event, sharedWorker.port)
}
Expand All @@ -37,12 +37,17 @@ export class ServiceWorkerInstance extends Worker {
constructor (filename, options) {
options = { ...options }
const info = options.info ?? null

if (info.serializedWorkerArgs) {
options.args = JSON.parse(decodeURIComponent(info.serializedWorkerArgs))
options.args.index = globalThis.__args.index
try {
options.args = JSON.parse(info.serializedWorkerArgs)
} catch {
try {
options.args = JSON.parse(decodeURIComponent(info.serializedWorkerArgs))
} catch {
options.args = JSON.parse(decodeURIComponent(decodeURIComponent(info.serializedWorkerArgs)))
}
}
}

super(filename, {
name: `ServiceWorker (${options?.info?.pathname ?? filename})`,
...options,
Expand Down Expand Up @@ -106,7 +111,7 @@ export class ServiceWorkerInstance extends Worker {
log.scrollTop = log.scrollHeight
}
} else if (event.data?.showNotification && event.data.registration?.id) {
onShowNotification(event, this)
onNotificationShow(event, this)
} else if (event.data?.getNotifications && event.data.registration?.id) {
onGetNotifications(event, this)
} else if (event.data?.notificationclose?.id) {
Expand All @@ -120,7 +125,6 @@ export class ServiceWorkerInfo {
url = null
hash = null
scope = null
scheme = null
scriptURL = null
serializedWorkerArgs = null

Expand All @@ -134,7 +138,7 @@ export class ServiceWorkerInfo {

const url = new URL(this.scriptURL)
this.url = url.toString()
this.hash = crypto.murmur3(this.scheme + url.pathname + (this.scope || ''))
this.hash = crypto.murmur3(url.pathname + (this.scope || ''))
}

get pathname () {
Expand Down Expand Up @@ -205,7 +209,7 @@ export async function onFetch (event) {
}
})(),
new Promise((resolve) => {
globalThis.addEventListener(
globalThis.top.addEventListener(
'serviceWorker.activate',
async function (event) {
// @ts-ignore
Expand Down Expand Up @@ -250,7 +254,7 @@ export async function onFetch (event) {
worker.postMessage({ fetch: { ...info, client, request } })
}

export function onShowNotification (event, target) {
export function onNotificationShow (event, target) {
for (const worker of workers.values()) {
if (worker.info.id === event.data.registration.id) {
let notification = null
Expand Down Expand Up @@ -353,14 +357,22 @@ export function onGetNotifications (event, target) {

export default null

globalThis.addEventListener('serviceWorker.register', onRegister)
globalThis.addEventListener('serviceWorker.unregister', onUnregister)
globalThis.addEventListener('serviceWorker.skipWaiting', onSkipWaiting)
globalThis.addEventListener('serviceWorker.activate', onActivate)
globalThis.addEventListener('serviceWorker.fetch', onFetch)
globalThis.top.addEventListener('serviceWorker.register', onRegister)
globalThis.top.addEventListener('serviceWorker.unregister', onUnregister)
globalThis.top.addEventListener('serviceWorker.skipWaiting', onSkipWaiting)
globalThis.top.addEventListener('serviceWorker.activate', onActivate)
globalThis.top.addEventListener('serviceWorker.fetch', onFetch)

hooks.onReady(async () => {
// notify top frame that the service worker init module is ready
globalThis.top.postMessage({
__service_worker_frame_init: true
})

channel.addEventListener('message', (e) => {
if (e.data?.type?.startsWith('serviceWorker.')) {
globalThis.dispatchEvent(new CustomEvent(e.data.type, e.data))
const result = await ipc.request('serviceWorker.getRegistrations')
if (Array.isArray(result.data)) {
for (const info of result.data) {
await navigator.serviceWorker.register(info.scriptURL, info)
}
}
})
11 changes: 9 additions & 2 deletions api/service-worker/instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function createServiceWorker (
}
}

const channel = new ipc.IPCBroadcastChannel('socket.runtime.serviceWorker.state')
const channel = new BroadcastChannel('socket.runtime.serviceWorker.state')

// events
const eventTarget = new EventTarget()
Expand Down Expand Up @@ -77,7 +77,14 @@ export function createServiceWorker (
state: {
configurable: true,
enumerable: false,
get: () => currentState === null ? state.serviceWorker.state : currentState
get: () => currentState === null ? state.serviceWorker.state : currentState,
},

[Symbol.for('socket.runtime.serviceWorker.state')]: {
configurable: false,
enumerable: false,
get: () => currentState === null ? state.serviceWorker.state : currentState,
set: (state) => { currentState = state }
},

scriptURL: {
Expand Down
Loading

0 comments on commit 863b4b2

Please sign in to comment.