Skip to content

Commit 3b79aa6

Browse files
committed
docs: clarify StikDebug script handling
1 parent 538a8bb commit 3b79aa6

1 file changed

Lines changed: 46 additions & 13 deletions

File tree

INTEGRATION.md

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This guide separates two different jobs:
99
- **Part 1: Add iOS 26 JIT support** changes the app's JIT memory allocator so it can cooperate with a script where TXM/SPTM is present.
1010
- **Part 2: Integrate StikDebug and StikJIT** adds the StikDebug URL scheme and optional Built-in StikJIT to an app that already works with iOS 26 JIT and manual StikDebug activation.
1111

12-
If the app already enables JIT successfully after the user manually selects it and its script in StikDebug, skip Part 1. Record the script filename and complete Part 2. Part 2 does not require changing a working JIT allocator.
12+
If the app already enables JIT successfully after the user manually selects it and its script in StikDebug, skip Part 1. Record whether it uses `universal.js`, `legacy.js`, or a custom script file, then complete Part 2. Part 2 does not require changing a working JIT allocator.
1313

1414
If the app does not already have script-based iOS 26 JIT, complete Part 1 first and then Part 2.
1515

@@ -56,11 +56,9 @@ Use this order where TXM/SPTM is present:
5656
5757
Preallocate executable regions before detaching. A region introduced later cannot be prepared by a script that has already detached; reconnect and repeat the protocol if the engine must add one.
5858
59-
## Keep the legacy protocol only for backward compatibility
59+
> **Note:** We keep legacy script support only for backward compatibility with existing applications. If you are adding JIT support to an app now, use the universal script.
6060
61-
The legacy script is retained only for existing engines that stop once at `brk #0x69` with the RX address in `x0` and its length in `x1`. It prepares that region, advances the program counter, and detaches. Do not build new integrations around `legacy.js`; implement the universal protocol instead.
62-
63-
After Part 1 works with the matching script in StikDebug, continue with Part 2. The chosen script filename is developer-controlled and must not become a user setting.
61+
After Part 1 works with the matching script in StikDebug, continue with Part 2. The chosen script is developer-controlled and must not become a user setting.
6462
6563
# Part 2: Integrate StikDebug and StikJIT into an existing iOS 26 JIT app
6664
@@ -69,7 +67,9 @@ Part 2 assumes all of the following already work:
6967
- The app can wait for an external debugger and detect when JIT is ready.
7068
- The app's JIT allocator implements its iOS 26 breakpoint and executable-region protocol.
7169
- JIT works when the developer or user manually selects the app and matching script in StikDebug.
72-
- The developer knows which script filename the app requires, normally `universal.js`.
70+
- The developer knows whether the app requires `universal.js`, `legacy.js`, or a custom script file.
71+
72+
If the app currently uses `legacy.js`, we recommend switching it to the universal method, but this is not required to complete Part 2.
7373
7474
Part 2 preserves that existing **Wait for Debugger** path and adds automatic StikDebug URL launching and optional Built-in StikJIT. It does not change the app's JIT allocator or script protocol. If any prerequisite above is missing, complete Part 1 first.
7575
@@ -262,7 +262,7 @@ try StikJIT.enableJIT(
262262
)
263263
```
264264

265-
Use `.universal` for new integrations. Use `.legacy` only when preserving an existing `legacy.js` ABI, or `.custom(URL)` for another established protocol. A custom script must be readable from the helper-extension process. Keep that selection in backend code and use the corresponding filename in the StikDebug URL. Do not expose script selection to the user. The user-facing `forceScript` toggle only bypasses TXM detection and runs the developer-selected script regardless.
265+
Use `.universal` or `.legacy` for the corresponding bundled script, or `.custom(URL)` for another established protocol. A custom script must be readable from the helper-extension process. Keep that selection in backend code. For StikDebug requests, send the matching built-in filename for universal or legacy, or send the base64-encoded contents of a custom script. Do not expose script selection to the user. The user-facing `forceScript` toggle only bypasses TXM detection and runs the developer-selected script regardless.
266266

267267
### When the user resets the cache
268268

@@ -286,10 +286,16 @@ Route all three choices through the same host-side coordinator. Check `get-task-
286286

287287
For **Wait for Debugger**, keep the app's existing waiting and readiness behavior. Where TXM/SPTM is present, it must continue through the existing breakpoint protocol before reporting success; an ordinary debugger attachment without the correct script is not sufficient.
288288

289-
For **StikDebug**, construct the URL with `URLComponents` and include the bundle ID, current PID, and the developer-selected script filename:
289+
For **StikDebug**, always construct the URL with the bundle ID and current PID. If TXM/SPTM is present, also send the developer-selected script. Use `script-name=universal.js` or `script-name=legacy.js` for the scripts bundled with StikDebug. For any other script, base64-encode the file contents and send them as `script-data` instead. When TXM/SPTM is not present, omit both script parameters because debugger attachment alone enables JIT.
290290

291291
```swift
292-
private let stikDebugScriptName = "universal.js"
292+
private enum StikDebugScript {
293+
case universal
294+
case legacy
295+
case custom(URL)
296+
}
297+
298+
private let stikDebugScript: StikDebugScript = .universal
293299

294300
guard let bundleID = Bundle.main.bundleIdentifier else {
295301
showJITError("Could not determine the app's bundle ID.")
@@ -302,9 +308,34 @@ components.host = "enable-jit"
302308
components.queryItems = [
303309
URLQueryItem(name: "bundle-id", value: bundleID),
304310
URLQueryItem(name: "pid", value: String(getpid())),
305-
URLQueryItem(name: "script-name", value: stikDebugScriptName),
306311
]
307312

313+
if isTXMPresent {
314+
switch stikDebugScript {
315+
case .universal:
316+
components.queryItems?.append(
317+
URLQueryItem(name: "script-name", value: "universal.js")
318+
)
319+
case .legacy:
320+
components.queryItems?.append(
321+
URLQueryItem(name: "script-name", value: "legacy.js")
322+
)
323+
case .custom(let scriptURL):
324+
do {
325+
let scriptData = try Data(contentsOf: scriptURL)
326+
components.queryItems?.append(
327+
URLQueryItem(
328+
name: "script-data",
329+
value: scriptData.base64EncodedString()
330+
)
331+
)
332+
} catch {
333+
showJITError("Could not read the StikDebug script: \(error.localizedDescription)")
334+
return
335+
}
336+
}
337+
}
338+
308339
guard let url = components.url else {
309340
showJITError("Could not create the StikDebug request.")
310341
return
@@ -313,7 +344,7 @@ guard let url = components.url else {
313344
UIApplication.shared.open(url)
314345
```
315346

316-
Use `universal.js` for new integrations. Specify `legacy.js` only for an app that already implements the legacy ABI, or another installed script for an established custom protocol. Keep this choice in developer-controlled backend code and do not expose `script-name` as a user setting. StikDebug uses the PID to target the running process and the bundle ID to identify and return to the app.
347+
Send custom scripts through `script-data`; do not require users to install them in StikDebug. Keep script selection in developer-controlled backend code and do not expose it as a user setting. Resolve TXM/SPTM presence before building the request rather than treating an unknown result as absent. StikDebug uses the PID to target the running process and the bundle ID to identify and return to the app.
317348

318349
If the app checks whether StikDebug is installed with `canOpenURL`, add this to its `Info.plist`:
319350

@@ -385,15 +416,17 @@ After completing Part 1, Part 2, or both, please get in touch with us in the [id
385416

386417
## All methods
387418

388-
- [ ] New iOS 26 integrations implement the universal protocol; legacy is used only for backward compatibility.
419+
- [ ] New iOS 26 integrations implement the universal protocol.
389420
- [ ] The host checks its own `get-task-allow` before starting JIT acquisition.
390421
- [ ] The selected script matches the app's breakpoint protocol and is not user-configurable.
391422
- [ ] Where TXM/SPTM is present, executable-region preparation succeeds before the workload starts.
392423
- [ ] Settings offer one mutually exclusive JIT method selection and start only that method.
393424

394425
### StikDebug
395426

396-
- [ ] The URL includes bundle ID, current PID, and the developer-selected `script-name`.
427+
- [ ] The URL always includes bundle ID and current PID.
428+
- [ ] Where TXM/SPTM is present, the URL includes `script-name` for universal or legacy, or base64-encoded `script-data` for a custom script.
429+
- [ ] Where TXM/SPTM is not present, the URL omits both script parameters.
397430
- [ ] `stikdebug` is in `LSApplicationQueriesSchemes` if the app calls `canOpenURL`.
398431
- [ ] The app does not treat successful URL opening as successful JIT acquisition.
399432
- [ ] Inside LiveContainer, the app tells users to enable **Use LiveContainer's Bundle ID**.

0 commit comments

Comments
 (0)