serve-sim 0.1.44-beta.98.1 → 0.1.44-beta.99.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -2,6 +2,18 @@ import Foundation
|
|
|
2
2
|
import ObjectiveC
|
|
3
3
|
import Darwin
|
|
4
4
|
|
|
5
|
+
/// Per-event HID logging is gated behind `SERVE_SIM_DEBUG_HID`. These lines fire
|
|
6
|
+
/// on every touch/move/button/key/crown event — a single drag emits a dozen —
|
|
7
|
+
/// so by default they flood stdout (and anything mirroring it) for no benefit.
|
|
8
|
+
/// Failure diagnostics ("returned nil", "unavailable", "not found") stay on
|
|
9
|
+
/// `print` so real problems are always visible.
|
|
10
|
+
private let hidDebugEnabled = ProcessInfo.processInfo.environment["SERVE_SIM_DEBUG_HID"] != nil
|
|
11
|
+
|
|
12
|
+
@inline(__always)
|
|
13
|
+
private func hidLog(_ message: @autoclosure () -> String) {
|
|
14
|
+
if hidDebugEnabled { print(message()) }
|
|
15
|
+
}
|
|
16
|
+
|
|
5
17
|
/// Injects touch, button, and orientation HID events into the iOS Simulator.
|
|
6
18
|
///
|
|
7
19
|
/// Uses IndigoHIDMessageForMouseNSEvent to create touch messages and
|
|
@@ -70,28 +82,28 @@ final class HIDInjector {
|
|
|
70
82
|
|
|
71
83
|
if let buttonPtr = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "IndigoHIDMessageForButton") {
|
|
72
84
|
self.buttonFunc = unsafeBitCast(buttonPtr, to: IndigoButtonFunc.self)
|
|
73
|
-
|
|
85
|
+
hidLog("[hid] IndigoHIDMessageForButton loaded")
|
|
74
86
|
} else {
|
|
75
87
|
print("[hid] Warning: IndigoHIDMessageForButton not found")
|
|
76
88
|
}
|
|
77
89
|
|
|
78
90
|
if let arbPtr = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "IndigoHIDMessageForHIDArbitrary") {
|
|
79
91
|
self.hidArbitraryFunc = unsafeBitCast(arbPtr, to: IndigoHIDArbitraryFunc.self)
|
|
80
|
-
|
|
92
|
+
hidLog("[hid] IndigoHIDMessageForHIDArbitrary loaded")
|
|
81
93
|
} else {
|
|
82
94
|
print("[hid] Warning: IndigoHIDMessageForHIDArbitrary not found")
|
|
83
95
|
}
|
|
84
96
|
|
|
85
97
|
if let keyboardPtr = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "IndigoHIDMessageForKeyboardArbitrary") {
|
|
86
98
|
self.keyboardFunc = unsafeBitCast(keyboardPtr, to: IndigoKeyboardFunc.self)
|
|
87
|
-
|
|
99
|
+
hidLog("[hid] IndigoHIDMessageForKeyboardArbitrary loaded")
|
|
88
100
|
} else {
|
|
89
101
|
print("[hid] Warning: IndigoHIDMessageForKeyboardArbitrary not found")
|
|
90
102
|
}
|
|
91
103
|
|
|
92
104
|
if let crownPtr = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "IndigoHIDMessageForDigitalCrownEvent") {
|
|
93
105
|
self.digitalCrownFunc = unsafeBitCast(crownPtr, to: IndigoDigitalCrownFunc.self)
|
|
94
|
-
|
|
106
|
+
hidLog("[hid] IndigoHIDMessageForDigitalCrownEvent loaded")
|
|
95
107
|
} else {
|
|
96
108
|
print("[hid] Warning: IndigoHIDMessageForDigitalCrownEvent not found")
|
|
97
109
|
}
|
|
@@ -120,8 +132,8 @@ final class HIDInjector {
|
|
|
120
132
|
|
|
121
133
|
self.hidClient = clientObj
|
|
122
134
|
self.sendSel = NSSelectorFromString("sendWithMessage:freeWhenDone:completionQueue:completion:")
|
|
123
|
-
|
|
124
|
-
|
|
135
|
+
hidLog("[hid] SimDeviceLegacyHIDClient created")
|
|
136
|
+
hidLog("[hid] IndigoHIDMessageForMouseNSEvent loaded (with edge gesture support)")
|
|
125
137
|
}
|
|
126
138
|
|
|
127
139
|
// IndigoHIDEdge values (x4 param to IndigoHIDMessageForMouseNSEvent).
|
|
@@ -175,7 +187,7 @@ final class HIDInjector {
|
|
|
175
187
|
|
|
176
188
|
func sendTouch(type: String, x: Double, y: Double, screenWidth: Int, screenHeight: Int, edge: UInt32 = 0) {
|
|
177
189
|
guard let msg = touchMessage(type: type, x: x, y: y, edge: edge) else { return }
|
|
178
|
-
|
|
190
|
+
hidLog("[hid] Sending \(type) at (\(String(format:"%.3f",x)),\(String(format:"%.3f",y)))\(edge > 0 ? " edge=\(edge)" : "")")
|
|
179
191
|
inputQueue.async { [self] in rawSend(msg) }
|
|
180
192
|
}
|
|
181
193
|
|
|
@@ -197,7 +209,7 @@ final class HIDInjector {
|
|
|
197
209
|
return
|
|
198
210
|
}
|
|
199
211
|
|
|
200
|
-
|
|
212
|
+
hidLog("[hid] Multi-touch \(type) f1=(\(String(format:"%.3f",x1)),\(String(format:"%.3f",y1))) f2=(\(String(format:"%.3f",x2)),\(String(format:"%.3f",y2)))")
|
|
201
213
|
inputQueue.async { [self] in rawSend(rawMsg) }
|
|
202
214
|
}
|
|
203
215
|
|
|
@@ -257,7 +269,7 @@ final class HIDInjector {
|
|
|
257
269
|
return
|
|
258
270
|
}
|
|
259
271
|
|
|
260
|
-
|
|
272
|
+
hidLog("[hid] Key \(type) usage=0x\(String(usage, radix: 16))")
|
|
261
273
|
inputQueue.async { [self] in rawSend(msg) }
|
|
262
274
|
}
|
|
263
275
|
|
|
@@ -277,7 +289,7 @@ final class HIDInjector {
|
|
|
277
289
|
return
|
|
278
290
|
}
|
|
279
291
|
|
|
280
|
-
|
|
292
|
+
hidLog("[hid] Digital Crown delta=\(String(format:"%.4f", delta))")
|
|
281
293
|
inputQueue.async { [self] in rawSend(msg) }
|
|
282
294
|
}
|
|
283
295
|
|
|
@@ -397,7 +409,7 @@ final class HIDInjector {
|
|
|
397
409
|
}
|
|
398
410
|
rawSend(msg)
|
|
399
411
|
}
|
|
400
|
-
|
|
412
|
+
hidLog("[hid] HID button page=\(page) usage=\(usage) phase=\(phase)")
|
|
401
413
|
inputQueue.async {
|
|
402
414
|
switch phase {
|
|
403
415
|
case "down": emit(1)
|
|
@@ -411,7 +423,7 @@ final class HIDInjector {
|
|
|
411
423
|
}
|
|
412
424
|
|
|
413
425
|
func sendButton(button: String, deviceUDID: String) {
|
|
414
|
-
|
|
426
|
+
hidLog("[hid] Sending button: \(button)")
|
|
415
427
|
|
|
416
428
|
switch button {
|
|
417
429
|
case "home":
|
|
@@ -490,7 +502,7 @@ final class HIDInjector {
|
|
|
490
502
|
let imp = device.method(for: sel)
|
|
491
503
|
let fn = unsafeBitCast(imp, to: Fn.self)
|
|
492
504
|
let result = fn(device, sel, name as NSString, ObjCBool(enabled))
|
|
493
|
-
|
|
505
|
+
hidLog("[sim] setCADebugOption(\(name), \(enabled)) → \(result.boolValue)")
|
|
494
506
|
return result.boolValue
|
|
495
507
|
}
|
|
496
508
|
|
|
@@ -523,7 +535,7 @@ final class HIDInjector {
|
|
|
523
535
|
return
|
|
524
536
|
}
|
|
525
537
|
_ = device.perform(sel)
|
|
526
|
-
|
|
538
|
+
hidLog("[sim] simulateMemoryWarning dispatched")
|
|
527
539
|
}
|
|
528
540
|
|
|
529
541
|
/// Synthesize a swipe-up-from-bottom gesture (Face ID "go home" gesture).
|
|
@@ -629,7 +641,7 @@ final class HIDInjector {
|
|
|
629
641
|
fputs("[hid] sendOrientation: mach_msg_send failed (\(kr))\n", stderr)
|
|
630
642
|
return false
|
|
631
643
|
} else {
|
|
632
|
-
|
|
644
|
+
hidLog("[hid] Orientation set to \(orientation)")
|
|
633
645
|
return true
|
|
634
646
|
}
|
|
635
647
|
}
|
package/dist/middleware.js
CHANGED
|
@@ -40,7 +40,7 @@ function __sd_simulate(p){
|
|
|
40
40
|
`+_)}function M(X,L,_,P,j,q){if(X.listenerCount("wsClientError")){let S=Error(j);Error.captureStackTrace(S,M),X.emit("wsClientError",S,_,L)}else R(_,P,j,q)}});MJ=YQ(e8(),1),FJ=YQ(J4(),1),NJ=YQ(vQ(),1),LJ=YQ(f5(),1),_J=YQ(b5(),1),RJ=YQ(h5(),1),_9=YQ(Y4(),1),i5=YQ(Q9(),1),k5=_9.default;q9={"Network.setUserAgentOverride":"Page.overrideUserAgent","Network.setCacheDisabled":"Network.setResourceCachingDisabled"},I9={"Network.requestWillBeSent":{walltime:"wallTime"}},x9={hasUserGesture:!1,redirectHasExtraInfo:!1},S9={hasExtraInfo:!1},w9={encodedDataLength:0,shouldReportCorbBlocking:!1},y9={initialPriority:"Medium",referrerPolicy:"origin"},k9={connectionReused:!1,connectionId:0,fromDiskCache:!1,fromServiceWorker:!1,encodedDataLength:0};d9={"media-rule":"mediaRule","media-import-rule":"importRule","media-style-node":"inlineSheet","media-link-node":"linkedSheet"};r9={protocolVersion:"1.3",product:"Safari/inspect-webkit",revision:"605.1.15",userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS like Mac OS X) AppleWebKit/605.1.15 Safari/inspect-webkit",jsVersion:""};Y$=["Animation","Autofill","Audits","ServiceWorker","Profiler","HeapProfiler","Storage","Tethering","Tracing","BackgroundService","FedCm","DeviceAccess","WebAuthn","Cast","Database","ApplicationCache","BackgroundFetch","DeviceOrientation","EventBreakpoints","FileSystem","HeadlessExperimental","IndexedDB","Memory","PerformanceTimeline","Performance","Preload","Schema","Security","SystemInfo","WebAudio"],G$={"Network.setAttachDebugStack":{},"Network.emulateNetworkConditionsByRule":{ruleIds:[]},"Network.overrideNetworkState":{},"Network.clearAcceptedEncodingsOverride":{},"Network.setAcceptedEncodings":{},"Network.enableReportingApi":{},"Overlay.setShowHinge":{},"Overlay.setShowViewportSizeOnResize":{},"Overlay.setShowGridOverlays":{},"Overlay.setShowFlexOverlays":{},"Overlay.setShowScrollSnapOverlays":{},"Overlay.setShowContainerQueryOverlays":{},"Overlay.setShowIsolatedElements":{},"Overlay.setPausedInDebuggerMessage":{},"Overlay.setShowAdHighlights":{},"Overlay.setShowDebugBorders":{},"Overlay.setShowFPSCounter":{},"Overlay.setShowLayoutShiftRegions":{},"Overlay.setShowScrollBottleneckRects":{},"Overlay.setShowHitTestBorders":{},"Overlay.setShowWebVitals":{},"CSS.trackComputedStyleUpdates":{},"CSS.takeComputedStyleUpdates":{nodeIds:[]},"CSS.startRuleUsageTracking":{},"CSS.stopRuleUsageTracking":{ruleUsage:[]},"CSS.takeCoverageDelta":{coverage:[],timestamp:0},"Page.setAdBlockingEnabled":{},"Page.removeScriptToEvaluateOnNewDocument":{},"Page.setBypassCSP":{},"Page.setInterceptFileChooserDialog":{},"Page.setPrerenderingAllowed":{},"Page.setRPHRegistrationMode":{},"Page.setSPCTransactionMode":{},"Emulation.setEmulatedVisionDeficiency":{},"Emulation.setFocusEmulationEnabled":{},"Emulation.setAutoDarkModeOverride":{},"Emulation.setAutomationOverride":{},"Emulation.setLocaleOverride":{},"Emulation.setTimezoneOverride":{},"Emulation.setVisibleSize":{},"Emulation.setIdleOverride":{},"Emulation.clearIdleOverride":{},"Emulation.setGeolocationOverride":{},"Emulation.clearGeolocationOverride":{},"Emulation.setSensorOverrideEnabled":{},"Emulation.setSensorOverrideReadings":{},"Emulation.setHardwareConcurrencyOverride":{},"Emulation.setNavigatorOverrides":{},"Emulation.setPageScaleFactor":{},"Emulation.setScrollbarsHidden":{},"Emulation.setDocumentCookieDisabled":{},"DOMDebugger.setBreakOnCSPViolation":{},"Runtime.addBinding":{},"Runtime.removeBinding":{},"Debugger.setReturnValue":{},"Debugger.setBlackboxExecutionContexts":{},"Debugger.setInstrumentationBreakpoint":{},"DOM.markUndoableState":{},"DOM.undo":{},"DOM.redo":{},"DOM.copyTo":{nodeId:0},"DOM.collectClassNamesFromSubtree":{classNames:[]},"Accessibility.enable":{},"Accessibility.disable":{},"Accessibility.getFullAXTree":{nodes:[]},"Accessibility.getRootAXNode":{node:null},"Accessibility.getPartialAXTree":{nodes:[]},"Accessibility.queryAXTree":{nodes:[]},"Accessibility.getAXNodeAndAncestors":{nodes:[]},"Accessibility.getChildAXNodes":{nodes:[]}};X$={"&":"&","<":"<",">":">",'"':""","'":"'"}});import{readdirSync as j$,readFileSync as D$,existsSync as R6,unlinkSync as V6,watch as T$}from"fs";import{execSync as NQ,spawn as P$,exec as q$,execFile as lQ}from"child_process";import{tmpdir as I$}from"os";import{join as _4}from"path";import{createServer as x$}from"net";import{createHash as S$,randomBytes as w$,timingSafeEqual as y$}from"crypto";import{WebSocket as X6}from"ws";var R0="Accessibility unavailable on this simulator.";import{createRequire as p6}from"module";import{dirname as O0,join as U0}from"path";import{existsSync as c6}from"fs";import{fileURLToPath as x4}from"url";var m6=p6(import.meta.url),d6=1,n6=1,i6=2,SQ={portrait:1,portraitUpsideDown:2,landscapeRight:3,landscapeLeft:4};function o6(){let Q=[U0(O0(process.execPath),"native","serve-sim-native.node"),U0(O0(x4(import.meta.url)),"native","serve-sim-native.node"),U0(O0(x4(import.meta.url)),"..","dist","native","serve-sim-native.node")];for(let $ of Q)if(c6($))return $;throw Error(`serve-sim-native.node not found. Looked in:
|
|
41
41
|
${Q.join(`
|
|
42
42
|
`)}
|
|
43
|
-
Run \`bun run build.ts\` to build the native addon.`)}var A0;function cQ(){if(!A0)A0=m6(o6());return A0}class C0{handle;constructor(Q){this.handle=new(cQ()).SimHID(Q)}touch(Q,$,Z,J,Y,G=0){this.handle.touch(Q,$,Z,J,Y,G)}multiTouch(Q,$,Z,J,Y,G,V){this.handle.multiTouch(Q,$,Z,J,Y,G,V)}button(Q){this.handle.button(Q)}buttonHid(Q,$,Z="press"){this.handle.buttonHid(Q,$,Z)}key(Q,$){this.handle.key(Q,$)}scroll(Q,$,Z,J,Y,G){this.handle.scroll(Q,$,Y??NaN,G??NaN,Z,J)}digitalCrown(Q){this.handle.digitalCrown(Q)}orientation(Q){return this.handle.orientation(Q)}memoryWarning(){this.handle.memoryWarning()}softwareKeyboard(){this.handle.softwareKeyboard()}caDebug(Q,$){return this.handle.caDebug(Q,$)}}class B0{handle;constructor(Q,$){this.handle=new(cQ()).SimCapture(Q,(Z,J,Y,G,V)=>{$({codec:Z===d6?"avcc":"mjpeg",data:J,width:Y,height:G,isDescription:(V&n6)!==0,isKeyframe:(V&i6)!==0})})}start(){this.handle.start()}setAvccActive(Q){this.handle.setAvccActive(Q)}requestKeyframe(){this.handle.requestKeyframe()}screenSize(){return this.handle.screenSize()}stop(){this.handle.stop()}}function mQ(Q){return cQ().axDescribe(Q)}function dQ(Q){return cQ().axFrontmost(Q)}var E0=500,S4=500,a6=2000,r6=15000;function t6(Q){return Q[0]?.frame??{x:0,y:0,width:1,height:1}}function s6(Q,$){return Math.abs(Q.x-$.x)<0.5&&Math.abs(Q.y-$.y)<0.5&&Math.abs(Q.width-$.width)<0.5&&Math.abs(Q.height-$.height)<0.5}function e6(Q){let $=t6(Q),Z=[],J=(Y,G)=>{if(Z.length>=E0)return;let V=Y.frame;if(!s6(V,$))Z.push({id:Y.AXUniqueId??G,path:G,label:Y.AXLabel??"",value:Y.AXValue??"",role:Y.role_description,type:Y.type,enabled:Y.enabled!==!1,frame:V});for(let K=0;K<Y.children.length&&Z.length<E0;K++)J(Y.children[K],`${G}.${K}`)};for(let Y=0;Y<Q.length&&Z.length<E0;Y++)J(Q[Y],String(Y));return{screen:{width:$.width,height:$.height},elements:Z}}async function Q7(Q){let $;try{$=JSON.parse(await mQ(Q))}catch{return{screen:{width:1,height:1},elements:[],errors:[R0]}}return e6($)}function $7(Q){return Q?.errors?.includes(R0)??!1}function Z7(Q){return Q.elements.length>0&&Q.screen.width>1&&Q.screen.height>1}async function J7(Q){let $=[];try{let Z=await Q7(Q);if(Z.errors?.length)return Z;if(!Z7(Z))throw Error(`native AX returned ${Z.elements.length} elements in ${Z.screen.width}x${Z.screen.height} AX space`);return{...Z,errors:$}}catch(Z){$.push(Z.message||String(Z))}return{screen:{width:1,height:1},elements:[],errors:$}}function Y7(Q){return`data: ${JSON.stringify(Q)}
|
|
43
|
+
Run \`bun run build.ts\` to build the native addon.`)}var A0;function cQ(){if(!A0)A0=m6(o6());return A0}class C0{handle;constructor(Q){this.handle=new(cQ()).SimHID(Q)}guard(Q,$,Z){try{return $()}catch(J){return console.error(`[hid] ${Q} ignored bad input:`,J instanceof Error?J.message:J),Z}}touch(Q,$,Z,J,Y,G=0){this.guard("touch",()=>this.handle.touch(Q,$,Z,J,Y,G),void 0)}multiTouch(Q,$,Z,J,Y,G,V){this.guard("multiTouch",()=>this.handle.multiTouch(Q,$,Z,J,Y,G,V),void 0)}button(Q){this.guard("button",()=>this.handle.button(Q),void 0)}buttonHid(Q,$,Z="press"){this.guard("buttonHid",()=>this.handle.buttonHid(Q,$,Z),void 0)}key(Q,$){this.guard("key",()=>this.handle.key(Q,$),void 0)}scroll(Q,$,Z,J,Y,G){this.guard("scroll",()=>this.handle.scroll(Q,$,Y??NaN,G??NaN,Z,J),void 0)}digitalCrown(Q){this.guard("digitalCrown",()=>this.handle.digitalCrown(Q),void 0)}orientation(Q){return this.guard("orientation",()=>this.handle.orientation(Q),!1)}memoryWarning(){this.guard("memoryWarning",()=>this.handle.memoryWarning(),void 0)}softwareKeyboard(){this.guard("softwareKeyboard",()=>this.handle.softwareKeyboard(),void 0)}caDebug(Q,$){return this.guard("caDebug",()=>this.handle.caDebug(Q,$),!1)}}class B0{handle;constructor(Q,$){this.handle=new(cQ()).SimCapture(Q,(Z,J,Y,G,V)=>{$({codec:Z===d6?"avcc":"mjpeg",data:J,width:Y,height:G,isDescription:(V&n6)!==0,isKeyframe:(V&i6)!==0})})}start(){this.handle.start()}setAvccActive(Q){this.handle.setAvccActive(Q)}requestKeyframe(){this.handle.requestKeyframe()}screenSize(){return this.handle.screenSize()}stop(){this.handle.stop()}}function mQ(Q){return cQ().axDescribe(Q)}function dQ(Q){return cQ().axFrontmost(Q)}var E0=500,S4=500,a6=2000,r6=15000;function t6(Q){return Q[0]?.frame??{x:0,y:0,width:1,height:1}}function s6(Q,$){return Math.abs(Q.x-$.x)<0.5&&Math.abs(Q.y-$.y)<0.5&&Math.abs(Q.width-$.width)<0.5&&Math.abs(Q.height-$.height)<0.5}function e6(Q){let $=t6(Q),Z=[],J=(Y,G)=>{if(Z.length>=E0)return;let V=Y.frame;if(!s6(V,$))Z.push({id:Y.AXUniqueId??G,path:G,label:Y.AXLabel??"",value:Y.AXValue??"",role:Y.role_description,type:Y.type,enabled:Y.enabled!==!1,frame:V});for(let K=0;K<Y.children.length&&Z.length<E0;K++)J(Y.children[K],`${G}.${K}`)};for(let Y=0;Y<Q.length&&Z.length<E0;Y++)J(Q[Y],String(Y));return{screen:{width:$.width,height:$.height},elements:Z}}async function Q7(Q){let $;try{$=JSON.parse(await mQ(Q))}catch{return{screen:{width:1,height:1},elements:[],errors:[R0]}}return e6($)}function $7(Q){return Q?.errors?.includes(R0)??!1}function Z7(Q){return Q.elements.length>0&&Q.screen.width>1&&Q.screen.height>1}async function J7(Q){let $=[];try{let Z=await Q7(Q);if(Z.errors?.length)return Z;if(!Z7(Z))throw Error(`native AX returned ${Z.elements.length} elements in ${Z.screen.width}x${Z.screen.height} AX space`);return{...Z,errors:$}}catch(Z){$.push(Z.message||String(Z))}return{screen:{width:1,height:1},elements:[],errors:$}}function Y7(Q){return`data: ${JSON.stringify(Q)}
|
|
44
44
|
|
|
45
45
|
`}function G7({udid:Q}){let $=new Set,Z=null,J=null,Y=S4,G=!1,V=!1,N=()=>{if(V||$.size===0||Z)return;Z=setTimeout(K,Y)},K=async()=>{if(Z=null,V||G||$.size===0){N();return}G=!0;try{let H=await J7(Q),z=Y7(H);if(z!==J){for(let F of $)F.write(z);Y=S4}else Y=Math.min(Y*2,a6);if(J=z,$7(H))Y=r6}finally{G=!1,N()}};return{addClient(H){if(V)return()=>{};if($.add(H),J)H.write(J);return K(),()=>{if($.delete(H),$.size===0&&Z)clearTimeout(Z),Z=null}},dispose(){if(V)return;if(V=!0,Z)clearTimeout(Z),Z=null;$.clear(),J=null}}}function w4(){let Q=new Map;return{get($){let Z=Q.get($);if(Z)return Z;let J=G7({udid:$});return Q.set($,J),J},prune($){let Z=$ instanceof Set?$:new Set($);for(let[J,Y]of Q)if(!Z.has(J))Y.dispose(),Q.delete(J)},size(){return Q.size}}}var j0={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type"},y4=8388608,V7=4,X7=130,W7=Buffer.from(`\r
|
|
46
46
|
`,"ascii");function k4(Q){return Buffer.from(`--frame\r
|
|
Binary file
|
package/dist/serve-sim.js
CHANGED
|
@@ -49,7 +49,7 @@ Simulator-wide UI options:
|
|
|
49
49
|
`).map(($)=>$.trim()).join(" ")};m9.O=function(Q){return this.inspectOpts.colors=this.useColors,w4.inspect(Q,this.inspectOpts)}});var i9=YQ((q3,x6)=>{if(typeof process>"u"||process.type==="renderer"||!1||process.__nwjs)x6.exports=c9();else x6.exports=n9()});var K4,k6,w6,RQ,y4;var S6=GQ(()=>{K4=o8(i9(),1),k6=K4.default("serve-sim:cli"),w6=K4.default("serve-sim:helper"),RQ=K4.default("serve-sim:state"),y4=K4.default("serve-sim:mw")});var y6="Accessibility unavailable on this simulator.";import{createRequire as EZ}from"module";import{dirname as f6,join as b6}from"path";import{existsSync as TZ}from"fs";import{fileURLToPath as o9}from"url";function AZ(){let Q=[b6(f6(process.execPath),"native","serve-sim-native.node"),b6(f6(o9(import.meta.url)),"native","serve-sim-native.node"),b6(f6(o9(import.meta.url)),"..","dist","native","serve-sim-native.node")];for(let $ of Q)if(TZ($))return $;throw Error(`serve-sim-native.node not found. Looked in:
|
|
50
50
|
${Q.join(`
|
|
51
51
|
`)}
|
|
52
|
-
Run \`bun run build.ts\` to build the native addon.`)}function f4(){if(!v6)v6=jZ(AZ());return v6}class h6{handle;constructor(Q){this.handle=new(f4()).SimHID(Q)}touch(Q,$,Z,J,Y,G=0){this.handle.touch(Q,$,Z,J,Y,G)}multiTouch(Q,$,Z,J,Y,G,X){this.handle.multiTouch(Q,$,Z,J,Y,G,X)}button(Q){this.handle.button(Q)}buttonHid(Q,$,Z="press"){this.handle.buttonHid(Q,$,Z)}key(Q,$){this.handle.key(Q,$)}scroll(Q,$,Z,J,Y,G){this.handle.scroll(Q,$,Y??NaN,G??NaN,Z,J)}digitalCrown(Q){this.handle.digitalCrown(Q)}orientation(Q){return this.handle.orientation(Q)}memoryWarning(){this.handle.memoryWarning()}softwareKeyboard(){this.handle.softwareKeyboard()}caDebug(Q,$){return this.handle.caDebug(Q,$)}}class u6{handle;constructor(Q,$){this.handle=new(f4()).SimCapture(Q,(Z,J,Y,G,X)=>{$({codec:Z===OZ?"avcc":"mjpeg",data:J,width:Y,height:G,isDescription:(X&qZ)!==0,isKeyframe:(X&DZ)!==0})})}start(){this.handle.start()}setAvccActive(Q){this.handle.setAvccActive(Q)}requestKeyframe(){this.handle.requestKeyframe()}screenSize(){return this.handle.screenSize()}stop(){this.handle.stop()}}function b4(Q){return f4().axDescribe(Q)}function v4(Q){return f4().axFrontmost(Q)}var jZ,OZ=1,qZ=1,DZ=2,W4,v6;var h4=GQ(()=>{jZ=EZ(import.meta.url),W4={portrait:1,portraitUpsideDown:2,landscapeRight:3,landscapeLeft:4}});function IZ(Q){return Q[0]?.frame??{x:0,y:0,width:1,height:1}}function xZ(Q,$){return Math.abs(Q.x-$.x)<0.5&&Math.abs(Q.y-$.y)<0.5&&Math.abs(Q.width-$.width)<0.5&&Math.abs(Q.height-$.height)<0.5}function kZ(Q){let $=IZ(Q),Z=[],J=(Y,G)=>{if(Z.length>=g6)return;let X=Y.frame;if(!xZ(X,$))Z.push({id:Y.AXUniqueId??G,path:G,label:Y.AXLabel??"",value:Y.AXValue??"",role:Y.role_description,type:Y.type,enabled:Y.enabled!==!1,frame:X});for(let W=0;W<Y.children.length&&Z.length<g6;W++)J(Y.children[W],`${G}.${W}`)};for(let Y=0;Y<Q.length&&Z.length<g6;Y++)J(Q[Y],String(Y));return{screen:{width:$.width,height:$.height},elements:Z}}async function wZ(Q){let $;try{$=JSON.parse(await b4(Q))}catch{return{screen:{width:1,height:1},elements:[],errors:[y6]}}return kZ($)}function SZ(Q){return Q?.errors?.includes(y6)??!1}function yZ(Q){return Q.elements.length>0&&Q.screen.width>1&&Q.screen.height>1}async function fZ(Q){let $=[];try{let Z=await wZ(Q);if(Z.errors?.length)return Z;if(!yZ(Z))throw Error(`native AX returned ${Z.elements.length} elements in ${Z.screen.width}x${Z.screen.height} AX space`);return{...Z,errors:$}}catch(Z){$.push(Z.message||String(Z))}return{screen:{width:1,height:1},elements:[],errors:$}}function bZ(Q){return`data: ${JSON.stringify(Q)}
|
|
52
|
+
Run \`bun run build.ts\` to build the native addon.`)}function f4(){if(!v6)v6=jZ(AZ());return v6}class h6{handle;constructor(Q){this.handle=new(f4()).SimHID(Q)}guard(Q,$,Z){try{return $()}catch(J){return console.error(`[hid] ${Q} ignored bad input:`,J instanceof Error?J.message:J),Z}}touch(Q,$,Z,J,Y,G=0){this.guard("touch",()=>this.handle.touch(Q,$,Z,J,Y,G),void 0)}multiTouch(Q,$,Z,J,Y,G,X){this.guard("multiTouch",()=>this.handle.multiTouch(Q,$,Z,J,Y,G,X),void 0)}button(Q){this.guard("button",()=>this.handle.button(Q),void 0)}buttonHid(Q,$,Z="press"){this.guard("buttonHid",()=>this.handle.buttonHid(Q,$,Z),void 0)}key(Q,$){this.guard("key",()=>this.handle.key(Q,$),void 0)}scroll(Q,$,Z,J,Y,G){this.guard("scroll",()=>this.handle.scroll(Q,$,Y??NaN,G??NaN,Z,J),void 0)}digitalCrown(Q){this.guard("digitalCrown",()=>this.handle.digitalCrown(Q),void 0)}orientation(Q){return this.guard("orientation",()=>this.handle.orientation(Q),!1)}memoryWarning(){this.guard("memoryWarning",()=>this.handle.memoryWarning(),void 0)}softwareKeyboard(){this.guard("softwareKeyboard",()=>this.handle.softwareKeyboard(),void 0)}caDebug(Q,$){return this.guard("caDebug",()=>this.handle.caDebug(Q,$),!1)}}class u6{handle;constructor(Q,$){this.handle=new(f4()).SimCapture(Q,(Z,J,Y,G,X)=>{$({codec:Z===OZ?"avcc":"mjpeg",data:J,width:Y,height:G,isDescription:(X&qZ)!==0,isKeyframe:(X&DZ)!==0})})}start(){this.handle.start()}setAvccActive(Q){this.handle.setAvccActive(Q)}requestKeyframe(){this.handle.requestKeyframe()}screenSize(){return this.handle.screenSize()}stop(){this.handle.stop()}}function b4(Q){return f4().axDescribe(Q)}function v4(Q){return f4().axFrontmost(Q)}var jZ,OZ=1,qZ=1,DZ=2,W4,v6;var h4=GQ(()=>{jZ=EZ(import.meta.url),W4={portrait:1,portraitUpsideDown:2,landscapeRight:3,landscapeLeft:4}});function IZ(Q){return Q[0]?.frame??{x:0,y:0,width:1,height:1}}function xZ(Q,$){return Math.abs(Q.x-$.x)<0.5&&Math.abs(Q.y-$.y)<0.5&&Math.abs(Q.width-$.width)<0.5&&Math.abs(Q.height-$.height)<0.5}function kZ(Q){let $=IZ(Q),Z=[],J=(Y,G)=>{if(Z.length>=g6)return;let X=Y.frame;if(!xZ(X,$))Z.push({id:Y.AXUniqueId??G,path:G,label:Y.AXLabel??"",value:Y.AXValue??"",role:Y.role_description,type:Y.type,enabled:Y.enabled!==!1,frame:X});for(let W=0;W<Y.children.length&&Z.length<g6;W++)J(Y.children[W],`${G}.${W}`)};for(let Y=0;Y<Q.length&&Z.length<g6;Y++)J(Q[Y],String(Y));return{screen:{width:$.width,height:$.height},elements:Z}}async function wZ(Q){let $;try{$=JSON.parse(await b4(Q))}catch{return{screen:{width:1,height:1},elements:[],errors:[y6]}}return kZ($)}function SZ(Q){return Q?.errors?.includes(y6)??!1}function yZ(Q){return Q.elements.length>0&&Q.screen.width>1&&Q.screen.height>1}async function fZ(Q){let $=[];try{let Z=await wZ(Q);if(Z.errors?.length)return Z;if(!yZ(Z))throw Error(`native AX returned ${Z.elements.length} elements in ${Z.screen.width}x${Z.screen.height} AX space`);return{...Z,errors:$}}catch(Z){$.push(Z.message||String(Z))}return{screen:{width:1,height:1},elements:[],errors:$}}function bZ(Q){return`data: ${JSON.stringify(Q)}
|
|
53
53
|
|
|
54
54
|
`}function vZ({udid:Q}){let $=new Set,Z=null,J=null,Y=a9,G=!1,X=!1,H=()=>{if(X||$.size===0||Z)return;Z=setTimeout(W,Y)},W=async()=>{if(Z=null,X||G||$.size===0){H();return}G=!0;try{let z=await fZ(Q),K=bZ(z);if(K!==J){for(let M of $)M.write(K);Y=a9}else Y=Math.min(Y*2,CZ);if(J=K,SZ(z))Y=PZ}finally{G=!1,H()}};return{addClient(z){if(X)return()=>{};if($.add(z),J)z.write(J);return W(),()=>{if($.delete(z),$.size===0&&Z)clearTimeout(Z),Z=null}},dispose(){if(X)return;if(X=!0,Z)clearTimeout(Z),Z=null;$.clear(),J=null}}}function r9(){let Q=new Map;return{get($){let Z=Q.get($);if(Z)return Z;let J=vZ({udid:$});return Q.set($,J),J},prune($){let Z=$ instanceof Set?$:new Set($);for(let[J,Y]of Q)if(!Z.has(J))Y.dispose(),Q.delete(J)},size(){return Q.size}}}var g6=500,a9=500,CZ=2000,PZ=15000;var s9=GQ(()=>{h4()});function e9(Q){return Buffer.from(`--frame\r
|
|
55
55
|
Content-Type: image/jpeg\r
|
|
@@ -136,7 +136,7 @@ Usage:
|
|
|
136
136
|
serve-sim permissions reset <permission|all> <bundle-id> [-d <udid|name>]
|
|
137
137
|
serve-sim permissions list [bundle-id] [-d <udid|name>]
|
|
138
138
|
|
|
139
|
-
Permissions: ${_6().join(", ")}`),process.exit(1);let Y=J.device?o(J.device):$Q();if(!Y)console.error("No booted simulator. Boot one or pass -d <udid|name>."),process.exit(1);if(J.verb==="list"){let X={udid:Y,bundleId:J.bundleId??null,tcc:j7(Y,J.bundleId),location:q7(Y,J.bundleId),notifications:P7(Y,J.bundleId)};console.log(JSON.stringify(X,null,$?0:2)),process.exit(0)}let G=J.bundleId;try{if(J.permission==="all")for(let X of _6())O9(Y,"reset",X,void 0,G);else O9(Y,J.verb,J.permission,J.value,G)}catch(X){console.error(X?.message??String(X)),process.exit(1)}if($)console.log(JSON.stringify({udid:Y,verb:J.verb,permission:J.permission,value:J.value??null,bundleId:G}));else{let X=J.value?` (${J.value})`:"";console.log(`\uD83D\uDD10 ${J.verb} ${J.permission}${X} for ${G} on ${Y}`)}process.exit(0)}P6();S6();var qQ=A4(import.meta.url);function o2(){return"0.1.44-beta.
|
|
139
|
+
Permissions: ${_6().join(", ")}`),process.exit(1);let Y=J.device?o(J.device):$Q();if(!Y)console.error("No booted simulator. Boot one or pass -d <udid|name>."),process.exit(1);if(J.verb==="list"){let X={udid:Y,bundleId:J.bundleId??null,tcc:j7(Y,J.bundleId),location:q7(Y,J.bundleId),notifications:P7(Y,J.bundleId)};console.log(JSON.stringify(X,null,$?0:2)),process.exit(0)}let G=J.bundleId;try{if(J.permission==="all")for(let X of _6())O9(Y,"reset",X,void 0,G);else O9(Y,J.verb,J.permission,J.value,G)}catch(X){console.error(X?.message??String(X)),process.exit(1)}if($)console.log(JSON.stringify({udid:Y,verb:J.verb,permission:J.permission,value:J.value??null,bundleId:G}));else{let X=J.value?` (${J.value})`:"";console.log(`\uD83D\uDD10 ${J.verb} ${J.permission}${X} for ${G} on ${Y}`)}process.exit(0)}P6();S6();var qQ=A4(import.meta.url);function o2(){return"0.1.44-beta.99.3"}function x0(){if(!i(VQ))P8(VQ,{recursive:!0})}function e(Q){if(Q)return A8(Y4(Q));for(let $ of q4()){let Z=A8($);if(Z)return Z}return null}var s4={at:0,booted:null};function a2(){let Q=Date.now();if(s4.booted&&Q-s4.at<1000)return s4.booted;try{let $=t("xcrun simctl list devices booted -j",{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3000}),Z=JSON.parse($),J=new Set;for(let Y of Object.values(Z.devices))for(let G of Y)if(G.state==="Booted")J.add(G.udid);return s4={at:Q,booted:J},J}catch{return null}}function A8(Q){try{if(!i(Q))return RQ("state file missing %s",Q),null;let $=JSON.parse(WQ(Q,"utf-8"));try{process.kill($.pid,0)}catch{return RQ("helper pid %d dead, removing stale state %s",$.pid,Q),rQ(Q),null}let Z=a2();if(Z&&!Z.has($.device)){RQ("helper pid %d bound to non-booted device %s — killing stale helper",$.pid,$.device),console.error(`[serve-sim] Helper pid ${$.pid} is bound to device ${$.device} which is no longer booted — killing stale helper.`);try{process.kill($.pid,"SIGTERM")}catch{}try{rQ(Q)}catch{}return null}return RQ("state ok pid=%d device=%s port=%d",$.pid,$.device,$.port),$}catch($){return RQ("readStateFile threw for %s: %o",Q,$),null}}function F4(){let Q=[];for(let $ of q4()){let Z=A8($);if(Z)Q.push(Z)}return Q}function r2(Q){x0(),k8(Y4(Q.device),JSON.stringify(Q,null,2)),RQ("wrote state pid=%d device=%s port=%d",Q.pid,Q.device,Q.port)}function bQ(Q){if(Q){RQ("clearState device=%s",Q);try{rQ(Y4(Q))}catch{}}else{RQ("clearState (all)");for(let $ of q4())try{rQ($)}catch{}}}function w8(){try{let Q=t("xcrun simctl list devices -j",{encoding:"utf-8"}),$=JSON.parse(Q),Z=Object.keys($.devices).filter((J)=>/SimRuntime\.iOS-/i.test(J)).sort((J,Y)=>{let G=(J.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number),X=(Y.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number);return(X[0]??0)-(G[0]??0)||(X[1]??0)-(G[1]??0)});for(let J of Z){let G=($.devices[J]??[]).find((X)=>X.isAvailable!==!1&&/^iPhone\b/i.test(X.name));if(G)return{udid:G.udid,name:G.name}}}catch{}return null}function C0(Q){try{let $=t("xcrun simctl list devices -j",{encoding:"utf-8"}),Z=JSON.parse($);for(let J of Object.values(Z.devices))for(let Y of J)if(Y.udid===Q)return Y.name}catch{}return null}function k0(Q){try{let $=t("xcrun simctl list devices -j",{encoding:"utf-8"}),Z=JSON.parse($);for(let J of Object.values(Z.devices))for(let Y of J)if(Y.udid===Q)return Y.state==="Booted"}catch{}return!1}function e4(Q){try{return process.kill(Q,0),!0}catch{return!1}}function w0(Q){try{process.kill(Q,"SIGTERM")}catch{return}let $=Date.now()+500;while(Date.now()<$)try{process.kill(Q,0),AQ(25)}catch{return}try{process.kill(Q,"SIGKILL")}catch{}let Z=Date.now()+500;while(Date.now()<Z)try{process.kill(Q,0),AQ(25)}catch{return}}function s2(Q){if(!k0(Q))try{t(`xcrun simctl boot ${Q}`,{encoding:"utf-8",stdio:"pipe"})}catch($){let Z=($.stderr??$.message??"").toLowerCase();if(!Z.includes("booted")&&!Z.includes("current state"))throw Error(`Failed to boot device ${Q}: ${$.stderr||$.message}`)}try{t("open -ga Simulator",{encoding:"utf-8",stdio:"pipe",timeout:3000})}catch{}}function t2(){let Q=i2();for(let $ of Object.values(Q))for(let Z of $??[])if(Z.family==="IPv4"&&!Z.internal)return Z.address;return null}async function S0(Q){let $=new Set(F4().map((Z)=>Z.port));for(let Z=Q;Z<Q+100;Z++){if($.has(Z))continue;if(await F9(Z))return Z}throw Error(`No available port found in range ${Q}-${Q+99}`)}async function e2(Q){s2(Q);try{t(`xcrun simctl bootstatus ${Q} -b`,{encoding:"utf-8",stdio:"pipe",timeout:60000})}catch($){if(!k0(Q))console.error(`Device ${Q} failed to reach booted state: ${$.stderr||$.message}`),process.exit(1)}}function QY(Q){if(process.argv[0]&&/(^|\/)serve-sim$/.test(process.argv[0]))return{command:process.argv[0],args:Q};return{command:process.argv[0],args:[process.argv[1],...Q]}}async function $Y(Q,$=150000){let Z=Date.now();while(Date.now()-Z<$){let J=e(Q);if(J)return J;await new Promise((Y)=>setTimeout(Y,200))}return null}async function y0(Q,$,Z){w6("startHelper udid=%s port=%d detach=%s",Q,$,Z.detach);let J="127.0.0.1";x0(),bQ(Q),T9($);let Y=JQ(VQ,`server-${Q}.log`),G=I8(Y,"w"),{command:X,args:H}=QY([Q,"--port",String($),"--host",J]),W=P0(X,H,{detached:Z.detach,stdio:["ignore",G,G]});if(x8(G),Z.detach)W.unref();let z=await $Y(Q);if(!z){if(W.pid)w0(W.pid);let K="";try{K=WQ(Y,"utf-8").trim()}catch{}console.error(K?`Preview server failed:
|
|
140
140
|
${K}`:"Preview server failed to start"),process.exit(1)}return Z.detach?{pid:z.pid}:{pid:z.pid,child:W}}async function ZY(Q,$,Z){k6("follow devices=%o startPort=%d",Q,$);let J=Q.length>0?Q.map(o):(()=>{let z=$Q();if(z)return[z];let K=w8();if(!K)console.error("No device specified and no available iOS simulator found."),process.exit(1);if(!Z)console.log(`No booted simulator — booting ${K.name}...`);return[K.udid]})(),Y=new Map,G=[],X=$;for(let z of J){let K=e(z);if(K){if(!Z){let T=C0(z)??z;if(J.length>1)console.log(`
|
|
141
141
|
==> ${T} (${z}) <==`);console.log(` Already running on port ${K.port}`),console.log(` Stream: ${K.streamUrl}`),console.log(` WebSocket: ${K.wsUrl}`)}G.push(K);continue}X=await S0(X);let{child:M}=await y0(z,X,{detach:!1});if(M)Y.set(z,M);let L=e(z)??mQ(z,X,"/","127.0.0.1");if(G.push(L),!Z){let T=C0(z)??z;if(J.length>1)console.log(`
|
|
142
142
|
==> ${T} (${z}) <==`);console.log(` Stream: ${L.streamUrl}`),console.log(` WebSocket: ${L.wsUrl}`),console.log(` Port: ${X}`)}X++}if(G.length===1){let z=G[0];console.log(JSON.stringify({url:z.url,streamUrl:z.streamUrl,wsUrl:z.wsUrl,port:z.port,device:z.device}))}else console.log(JSON.stringify({devices:G.map((z)=>({url:z.url,streamUrl:z.streamUrl,wsUrl:z.wsUrl,port:z.port,device:z.device}))}));if(Y.size===0)return;let H=!1,W=(z)=>{if(H)return;if(H=!0,!Z)console.log(`
|
package/package.json
CHANGED
package/src/native.ts
CHANGED
|
@@ -116,49 +116,65 @@ export class NativeHid {
|
|
|
116
116
|
this.handle = new (load().SimHID)(udid);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
// The N-API bindings throw synchronously when a JS value can't be coerced to
|
|
120
|
+
// the native parameter type (e.g. a touch with a non-string `type` →
|
|
121
|
+
// "Could not convert parameter 0 to type String"). HID now runs in-process,
|
|
122
|
+
// so an unhandled throw here crashes the whole server — and if it lands
|
|
123
|
+
// mid-gesture, the guest is left with a stuck finger that wedges input until
|
|
124
|
+
// the sim reboots. The spawned helper used to absorb this in its own process;
|
|
125
|
+
// `guard` restores that isolation by swallowing malformed-input errors.
|
|
126
|
+
private guard<T>(op: string, fn: () => T, fallback: T): T {
|
|
127
|
+
try {
|
|
128
|
+
return fn();
|
|
129
|
+
} catch (err) {
|
|
130
|
+
console.error(`[hid] ${op} ignored bad input:`, err instanceof Error ? err.message : err);
|
|
131
|
+
return fallback;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
119
135
|
touch(type: TouchType, x: number, y: number, w: number, h: number, edge = 0): void {
|
|
120
|
-
this.handle.touch(type, x, y, w, h, edge);
|
|
136
|
+
this.guard("touch", () => this.handle.touch(type, x, y, w, h, edge), undefined);
|
|
121
137
|
}
|
|
122
138
|
|
|
123
139
|
multiTouch(type: TouchType, x1: number, y1: number, x2: number, y2: number, w: number, h: number): void {
|
|
124
|
-
this.handle.multiTouch(type, x1, y1, x2, y2, w, h);
|
|
140
|
+
this.guard("multiTouch", () => this.handle.multiTouch(type, x1, y1, x2, y2, w, h), undefined);
|
|
125
141
|
}
|
|
126
142
|
|
|
127
143
|
button(button: string): void {
|
|
128
|
-
this.handle.button(button);
|
|
144
|
+
this.guard("button", () => this.handle.button(button), undefined);
|
|
129
145
|
}
|
|
130
146
|
|
|
131
147
|
buttonHid(page: number, usage: number, phase: ButtonPhase = "press"): void {
|
|
132
|
-
this.handle.buttonHid(page, usage, phase);
|
|
148
|
+
this.guard("buttonHid", () => this.handle.buttonHid(page, usage, phase), undefined);
|
|
133
149
|
}
|
|
134
150
|
|
|
135
151
|
key(type: KeyType, usage: number): void {
|
|
136
|
-
this.handle.key(type, usage);
|
|
152
|
+
this.guard("key", () => this.handle.key(type, usage), undefined);
|
|
137
153
|
}
|
|
138
154
|
|
|
139
155
|
/** anchorX/anchorY default to screen center when omitted. */
|
|
140
156
|
scroll(dx: number, dy: number, w: number, h: number, anchorX?: number, anchorY?: number): void {
|
|
141
|
-
this.handle.scroll(dx, dy, anchorX ?? NaN, anchorY ?? NaN, w, h);
|
|
157
|
+
this.guard("scroll", () => this.handle.scroll(dx, dy, anchorX ?? NaN, anchorY ?? NaN, w, h), undefined);
|
|
142
158
|
}
|
|
143
159
|
|
|
144
160
|
digitalCrown(delta: number): void {
|
|
145
|
-
this.handle.digitalCrown(delta);
|
|
161
|
+
this.guard("digitalCrown", () => this.handle.digitalCrown(delta), undefined);
|
|
146
162
|
}
|
|
147
163
|
|
|
148
164
|
orientation(orientation: number): boolean {
|
|
149
|
-
return this.handle.orientation(orientation);
|
|
165
|
+
return this.guard("orientation", () => this.handle.orientation(orientation), false);
|
|
150
166
|
}
|
|
151
167
|
|
|
152
168
|
memoryWarning(): void {
|
|
153
|
-
this.handle.memoryWarning();
|
|
169
|
+
this.guard("memoryWarning", () => this.handle.memoryWarning(), undefined);
|
|
154
170
|
}
|
|
155
171
|
|
|
156
172
|
softwareKeyboard(): void {
|
|
157
|
-
this.handle.softwareKeyboard();
|
|
173
|
+
this.guard("softwareKeyboard", () => this.handle.softwareKeyboard(), undefined);
|
|
158
174
|
}
|
|
159
175
|
|
|
160
176
|
caDebug(name: string, enabled: boolean): boolean {
|
|
161
|
-
return this.handle.caDebug(name, enabled);
|
|
177
|
+
return this.guard("caDebug", () => this.handle.caDebug(name, enabled), false);
|
|
162
178
|
}
|
|
163
179
|
}
|
|
164
180
|
|