Skip to content

Commit

Permalink
refactor(src): rework runtime, context isolation per bundle id, prepa…
Browse files Browse the repository at this point in the history
…re for origin isolated service worker
  • Loading branch information
jwerle committed Dec 29, 2024
1 parent 4eecb05 commit 255c341
Show file tree
Hide file tree
Showing 266 changed files with 31,039 additions and 8,904 deletions.
233 changes: 175 additions & 58 deletions api/README.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions api/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ export function getCurrentWindowIndex () {
* @param {boolean=} [opts.headless=false] - whether the window will be headless or not (no frame)
* @param {string=} [opts.userScript=null] - A user script that will be injected into the window (desktop only)
* @param {string[]=} [opts.protocolHandlers] - An array of protocol handler schemes to register with the new window (requires service worker)
* @param {string=} [opts.resourcesDirectory]
* @param {boolean=} [opts.shouldPreferServiceWorker=false]
* @return {Promise<ApplicationWindow>}
*/
export async function createWindow (opts) {
Expand All @@ -262,7 +264,9 @@ export async function createWindow (opts) {
backgroundColorDark: opts.backgroundColorDark ?? '',
backgroundColorLight: opts.backgroundColorLight ?? '',
utility: opts.utility ?? false,
resourcesDirectory: opts.resourcesDirectory ?? '',
shouldExitApplicationOnClose: opts.shouldExitApplicationOnClose ?? false,
shouldPreferServiceWorker: Boolean(opts.shouldPreferServiceWorker ?? false),
/**
* @private
* @type {number}
Expand Down
14 changes: 7 additions & 7 deletions api/child_process/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const propagateWorkerError = err => parentPort.postMessage({
if (process.stdin) {
process.stdin.on('data', async (data) => {
const { id } = state
const result = await ipc.write('child_process.spawn', { id }, data)
const result = await ipc.write('childProcess.spawn', { id }, data)

if (result.err) {
propagateWorkerError(result.err)
Expand All @@ -42,7 +42,7 @@ parentPort.onmessage = async ({ data: { id, method, args } }) => {
stderr: opts?.stderr !== false
}

const result = await ipc.send('child_process.spawn', params)
const result = await ipc.send('childProcess.spawn', params)

if (result.err) {
return propagateWorkerError(result.err)
Expand All @@ -66,25 +66,25 @@ parentPort.onmessage = async ({ data: { id, method, args } }) => {

if (!data || BigInt(data.id) !== state.id) return

if (source === 'child_process.spawn' && data.source === 'stdout') {
if (source === 'childProcess.spawn' && data.source === 'stdout') {
if (process.stdout) {
process.stdout.write(buffer)
}
}

if (source === 'child_process.spawn' && data.source === 'stderr') {
if (source === 'childProcess.spawn' && data.source === 'stderr') {
if (process.stderr) {
process.stderr.write(buffer)
}
}

if (source === 'child_process.spawn' && data.status === 'close') {
if (source === 'childProcess.spawn' && data.status === 'close') {
state.exitCode = data.code
state.lifecycle = 'close'
parentPort.postMessage({ method: 'state', args: [state] })
}

if (source === 'child_process.spawn' && data.status === 'exit') {
if (source === 'childProcess.spawn' && data.status === 'exit') {
state.exitCode = data.code
state.lifecycle = 'exit'
parentPort.postMessage({ method: 'state', args: [state] })
Expand All @@ -93,7 +93,7 @@ parentPort.onmessage = async ({ data: { id, method, args } }) => {
}

if (method === 'kill') {
const result = await ipc.send('child_process.kill', {
const result = await ipc.send('childProcess.kill', {
id: state.id,
signal: signal.getCode(args[0])
})
Expand Down
14 changes: 5 additions & 9 deletions api/commonjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import URL from '../url.js'
import fs from '../fs.js'
import os from '../os.js'

const RUNTIME_SERVICE_WORKER_FETCH_MODE = 'Runtime-ServiceWorker-Fetch-Mode'
// TODO(@jwerle): investigate if we really need this header back
// const RUNTIME_SERVICE_WORKER_FETCH_MODE = 'Runtime-ServiceWorker-Fetch-Mode'
const RUNTIME_REQUEST_SOURCE_HEADER = 'Runtime-Request-Source'
const textDecoder = new TextDecoder()

Expand Down Expand Up @@ -209,7 +210,9 @@ export class RequestStatus {
}

if (
application.config.commonjs_fscheck !== false &&
os.platform() !== 'android' &&
/^(socket:|https:)/.test(this.id) &&
this.#request.id.includes(`://${application.config.meta_bundle_identifier}`)
) {
try {
Expand All @@ -227,10 +230,6 @@ export class RequestStatus {
request.open('HEAD', this.#request.id, false)
request.setRequestHeader(RUNTIME_REQUEST_SOURCE_HEADER, 'module')

if (globalThis.isServiceWorkerScope) {
request.setRequestHeader(RUNTIME_SERVICE_WORKER_FETCH_MODE, 'ignore')
}

if (this.#request?.loader) {
const entries = this.#request.loader.headers.entries()
for (const entry of entries) {
Expand Down Expand Up @@ -442,6 +441,7 @@ export class Request {
}

if (
application.config.commonjs_fscheck !== false &&
os.platform() !== 'android' &&
/^(socket:|https:)/.test(this.id) &&
this.id.includes(`//${application.config.meta_bundle_identifier}/`)
Expand All @@ -460,10 +460,6 @@ export class Request {
request.open('GET', this.id, false)
request.setRequestHeader(RUNTIME_REQUEST_SOURCE_HEADER, 'module')

if (globalThis.isServiceWorkerScope) {
request.setRequestHeader(RUNTIME_SERVICE_WORKER_FETCH_MODE, 'ignore')
}

if (typeof options?.responseType === 'string') {
request.responseType = options.responseType
}
Expand Down
64 changes: 33 additions & 31 deletions api/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,37 +115,39 @@ function dispatchReadyEvent (target) {

function proxyGlobalEvents (global, target) {
for (const type of GLOBAL_EVENTS) {
const globalObject = GLOBAL_TOP_LEVEL_EVENTS.includes(type)
? global.top ?? global
: global

addEventListener(globalObject, type, (event) => {
const { type, data, detail = null, error } = event
const { origin } = location

if (type === 'applicationurl') {
dispatchEvent(target, new ApplicationURLEvent(type, {
origin,
data: event.data,
url: event.url.toString()
}))
} else if (type === 'error' || error) {
const { message, filename = import.meta.url || globalThis.location.href } = error || {}
dispatchEvent(target, new ErrorEvent(type, {
message,
filename,
error,
detail,
origin
}))
} else if (data || type === 'message') {
dispatchEvent(target, new MessageEvent(type, event))
} else if (detail) {
dispatchEvent(target, new CustomEvent(type, event))
} else {
dispatchEvent(target, new Event(type, event))
}
})
try {
const globalObject = GLOBAL_TOP_LEVEL_EVENTS.includes(type)
? global.top ?? global
: global

addEventListener(globalObject, type, (event) => {
const { type, data, detail = null, error } = event
const { origin } = location

if (type === 'applicationurl') {
dispatchEvent(target, new ApplicationURLEvent(type, {
origin,
data: event.data,
url: event.url.toString()
}))
} else if (type === 'error' || error) {
const { message, filename = import.meta.url || globalThis.location.href } = error || {}
dispatchEvent(target, new ErrorEvent(type, {
message,
filename,
error,
detail,
origin
}))
} else if (data || type === 'message') {
dispatchEvent(target, new MessageEvent(type, event))
} else if (detail) {
dispatchEvent(target, new CustomEvent(type, event))
} else {
dispatchEvent(target, new Event(type, event))
}
})
} catch (err) {}
}
}

Expand Down
23 changes: 19 additions & 4 deletions api/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7884,6 +7884,8 @@ declare module "socket:application" {
* @param {boolean=} [opts.headless=false] - whether the window will be headless or not (no frame)
* @param {string=} [opts.userScript=null] - A user script that will be injected into the window (desktop only)
* @param {string[]=} [opts.protocolHandlers] - An array of protocol handler schemes to register with the new window (requires service worker)
* @param {string=} [opts.resourcesDirectory]
* @param {boolean=} [opts.shouldPreferServiceWorker=false]
* @return {Promise<ApplicationWindow>}
*/
export function createWindow(opts: {
Expand Down Expand Up @@ -7913,6 +7915,8 @@ declare module "socket:application" {
headless?: boolean | undefined;
userScript?: string | undefined;
protocolHandlers?: string[] | undefined;
resourcesDirectory?: string | undefined;
shouldPreferServiceWorker?: boolean | undefined;
}): Promise<ApplicationWindow>;
/**
* Returns the current screen size.
Expand Down Expand Up @@ -9434,7 +9438,7 @@ declare module "socket:internal/conduit" {
* @typedef {{ options: object, payload: Uint8Array }} ReceiveMessage
* @typedef {function(Error?, ReceiveCallback | undefined)} ReceiveCallback
* @typedef {{ isActive: boolean, handles: { ids: string[], count: number }}} ConduitDiagnostics
* @typedef {{ isActive: boolean, port: number }} ConduitStatus
* @typedef {{ isActive: boolean, port: number, sharedKey: string }} ConduitStatus
* @typedef {{
* id?: string|BigInt|number,
* sharedKey?: string
Expand Down Expand Up @@ -9476,6 +9480,17 @@ declare module "socket:internal/conduit" {
static waitForActiveState(options?: {
maxQueriesForStatus?: number;
} | undefined): Promise<any>;
/**
* Gets the current conduit shared key.
* @return {Promise<string>}
*/
static getSharedKey(): Promise<string>;
/**
* Sets the conduit shared key.
* @param {string} sharedKey
* @return {Promise<string>}
*/
static setSharedKey(sharedKey: string): Promise<string>;
/**
* Creates an instance of Conduit.
*
Expand Down Expand Up @@ -9503,9 +9518,9 @@ declare module "socket:internal/conduit" {
*/
port: number;
/**
* @type {number?}
* @type {string}
*/
id: number | null;
id: string;
/**
* @type {string}
*/
Expand Down Expand Up @@ -9611,6 +9626,7 @@ declare module "socket:internal/conduit" {
export type ConduitStatus = {
isActive: boolean;
port: number;
sharedKey: string;
};
export type ConduitOptions = {
id?: string | BigInt | number;
Expand Down Expand Up @@ -10571,7 +10587,6 @@ declare module "socket:internal/database" {
delete(key: string, options?: (DatabaseDeleteOptions | undefined) | null): Promise<any>;
/**
* Gets a "readonly" value by `key` in the `Database` object storage.
* @param {string} key
* @param {?DatabaseEntriesOptions|undefined} [options]
* @return {Promise<object|object[]|null>}
*/
Expand Down
Loading

0 comments on commit 255c341

Please sign in to comment.