@thelacanians/vue-native-cli 0.4.15 → 0.6.2
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.
- package/dist/cli.js +329 -15
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/NativeBridge.kt +118 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VViewFactory.kt +178 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/GeneratedModuleRegistry.kt +28 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModuleRegistry.kt +3 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ComponentFactoryTest.kt +674 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ErrorOverlayViewTest.kt +183 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/EventThrottleTest.kt +203 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/HotReloadManagerTest.kt +162 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/JSPolyfillsTest.kt +153 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeBridgeTest.kt +6 -3
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeModuleTest.kt +475 -0
- package/native/android/gradle.properties +1 -0
- package/native/android/gradlew +1 -1
- package/native/ios/VueNativeCore/Package.swift +1 -1
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/EventThrottle.swift +1 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/NativeBridge.swift +143 -5
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VTextFactory.swift +43 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift +116 -4
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/GestureWrapper.swift +100 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/GeneratedModuleRegistry.swift +28 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModuleRegistry.swift +3 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/CertificatePinningTests.swift +190 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/ComponentFactoryTests.swift +585 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/EventThrottleTests.swift +161 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/HotReloadManagerTests.swift +88 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/JSPolyfillsTests.swift +319 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/NativeModuleTests.swift +400 -0
- package/native/macos/VueNativeMacOS/Package.swift +34 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/ErrorOverlayView.swift +112 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/EventThrottle.swift +58 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/HotReloadManager.swift +153 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSPolyfills.swift +696 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSRuntime.swift +347 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/NativeBridge.swift +877 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/VueNativeWindowController.swift +125 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/ComponentRegistry.swift +209 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActionSheetFactory.swift +155 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActivityIndicatorFactory.swift +85 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VAlertDialogFactory.swift +132 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VButtonFactory.swift +83 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VCheckboxFactory.swift +108 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VDropdownFactory.swift +155 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VImageFactory.swift +270 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VInputFactory.swift +257 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VKeyboardAvoidingFactory.swift +22 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VListFactory.swift +324 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VModalFactory.swift +231 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VOutlineViewFactory.swift +276 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPickerFactory.swift +134 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPressableFactory.swift +120 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VProgressBarFactory.swift +71 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRadioFactory.swift +193 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRefreshControlFactory.swift +25 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSafeAreaFactory.swift +46 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VScrollViewFactory.swift +190 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSectionListFactory.swift +374 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSegmentedControlFactory.swift +125 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSliderFactory.swift +131 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSplitViewFactory.swift +215 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VStatusBarFactory.swift +25 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSwitchFactory.swift +92 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VTextFactory.swift +336 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VToolbarFactory.swift +212 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VVideoFactory.swift +245 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VViewFactory.swift +314 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VWebViewFactory.swift +162 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/NativeComponentFactory.swift +54 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/ClickableView.swift +100 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/Extensions.swift +23 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/GestureWrapper.swift +183 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/NSColor+Hex.swift +78 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/FlippedView.swift +19 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/LayoutNode.swift +493 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AnimationModule.swift +354 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AppStateModule.swift +62 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/BiometryModule.swift +60 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/CameraModule.swift +167 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ClipboardModule.swift +34 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DeviceInfoModule.swift +49 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DragDropModule.swift +50 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/FileDialogModule.swift +86 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/HapticsModule.swift +42 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/KeyboardModule.swift +28 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/LinkingModule.swift +49 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/MenuModule.swift +95 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NativeModuleRegistry.swift +63 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NotificationsModule.swift +112 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/PermissionsModule.swift +149 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ShareModule.swift +37 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/WindowModule.swift +71 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Resources/vue-native-placeholder.js +2 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Styling/StyleEngine.swift +885 -0
- package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/ComponentFactoryTests.swift +80 -0
- package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/VueNativeMacOSTests.swift +149 -0
- package/native/shared/VueNativeShared/AGENTS.md +129 -0
- package/native/shared/VueNativeShared/Package.swift +14 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/CertificatePinning.swift +134 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/EventThrottle.swift +78 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/HotReloadManager.swift +162 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/JSRuntime.swift +412 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AsyncStorageModule.swift +68 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AudioModule.swift +359 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/DatabaseModule.swift +259 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/FileSystemModule.swift +233 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/GeolocationModule.swift +156 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/NetworkModule.swift +59 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/PerformanceModule.swift +113 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/SecureStorageModule.swift +119 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/WebSocketModule.swift +212 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeEventDispatcher.swift +6 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModule.swift +26 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModuleRegistry.swift +37 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/SharedJSPolyfills.swift +673 -0
- package/native/shared/VueNativeShared/Tests/VueNativeSharedTests/VueNativeSharedTests.swift +44 -0
- package/package.json +8 -2
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import JavaScriptCore
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
// MARK: - Bundle Source
|
|
5
|
+
|
|
6
|
+
/// Describes where to load the JS application bundle from.
|
|
7
|
+
public enum BundleSource {
|
|
8
|
+
/// Load from an embedded resource in the app bundle.
|
|
9
|
+
case embedded(name: String)
|
|
10
|
+
/// Load from a development server URL (for live reload).
|
|
11
|
+
case devServer(url: URL)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// MARK: - JSRuntime
|
|
15
|
+
|
|
16
|
+
/// Core JavaScript runtime manager for macOS. Wraps JSContext on a dedicated serial DispatchQueue.
|
|
17
|
+
/// All JS operations are guaranteed to execute on the JS queue. AppKit operations
|
|
18
|
+
/// are never performed on this queue.
|
|
19
|
+
///
|
|
20
|
+
/// Thread safety contract:
|
|
21
|
+
/// - All JSContext access happens exclusively on `jsQueue`
|
|
22
|
+
/// - Never pass JSValue across threads -- extract primitives first
|
|
23
|
+
/// - All closures registered with JSContext use [weak self]
|
|
24
|
+
public final class JSRuntime: @unchecked Sendable {
|
|
25
|
+
|
|
26
|
+
// MARK: - Singleton
|
|
27
|
+
|
|
28
|
+
public static let shared = JSRuntime()
|
|
29
|
+
|
|
30
|
+
// MARK: - Properties
|
|
31
|
+
|
|
32
|
+
/// Dedicated serial queue for all JavaScript execution.
|
|
33
|
+
/// QoS is userInteractive because JS drives the UI pipeline.
|
|
34
|
+
public let jsQueue = DispatchQueue(label: "com.vuenative.macos.js", qos: .userInteractive)
|
|
35
|
+
|
|
36
|
+
/// The underlying JavaScriptCore context. Only access on jsQueue.
|
|
37
|
+
public private(set) var context: JSContext!
|
|
38
|
+
|
|
39
|
+
/// Whether the runtime has been initialized.
|
|
40
|
+
public private(set) var isInitialized = false
|
|
41
|
+
|
|
42
|
+
/// Startup time reference for performance.now()
|
|
43
|
+
public let startTime: CFAbsoluteTime = CFAbsoluteTimeGetCurrent()
|
|
44
|
+
|
|
45
|
+
// MARK: - Initialization
|
|
46
|
+
|
|
47
|
+
private init() {}
|
|
48
|
+
|
|
49
|
+
/// Initialize the JS runtime. Creates the JSContext on the JS queue,
|
|
50
|
+
/// configures exception handling, and registers polyfills.
|
|
51
|
+
/// Must be called before any other method.
|
|
52
|
+
public func initialize(completion: (() -> Void)? = nil) {
|
|
53
|
+
jsQueue.async { [weak self] in
|
|
54
|
+
guard let self = self else { return }
|
|
55
|
+
guard !self.isInitialized else {
|
|
56
|
+
completion?()
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
self.context = JSContext()
|
|
61
|
+
|
|
62
|
+
self.context.exceptionHandler = { [weak self] context, exception in
|
|
63
|
+
guard let exception = exception else { return }
|
|
64
|
+
let message = exception.toString() ?? "Unknown JS error"
|
|
65
|
+
let line = exception.objectForKeyedSubscript("line")?.toInt32() ?? 0
|
|
66
|
+
let column = exception.objectForKeyedSubscript("column")?.toInt32() ?? 0
|
|
67
|
+
let stack = exception.objectForKeyedSubscript("stack")?.toString() ?? ""
|
|
68
|
+
NSLog("[VueNative macOS JS Error] \(message) at line \(line):\(column)")
|
|
69
|
+
if !stack.isEmpty {
|
|
70
|
+
NSLog("[VueNative macOS JS Stack] \(stack)")
|
|
71
|
+
}
|
|
72
|
+
#if DEBUG
|
|
73
|
+
let fullMessage = stack.isEmpty ? message : "\(message)\n\n\(stack)"
|
|
74
|
+
ErrorOverlayView.show(error: fullMessage)
|
|
75
|
+
#endif
|
|
76
|
+
_ = self
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
self.context.evaluateScript("var globalThis = this;")
|
|
80
|
+
|
|
81
|
+
// Register polyfills
|
|
82
|
+
JSPolyfills.register(in: self)
|
|
83
|
+
|
|
84
|
+
self.isInitialized = true
|
|
85
|
+
completion?()
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// MARK: - Script Evaluation
|
|
90
|
+
|
|
91
|
+
/// Evaluate a JavaScript string on the JS queue.
|
|
92
|
+
public func evaluateScript(_ script: String, sourceURL: String? = nil, completion: ((JSValue?) -> Void)? = nil) {
|
|
93
|
+
jsQueue.async { [weak self] in
|
|
94
|
+
guard let self = self, let context = self.context else {
|
|
95
|
+
completion?(nil)
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let result: JSValue?
|
|
100
|
+
if let sourceURL = sourceURL, let url = URL(string: sourceURL) {
|
|
101
|
+
result = context.evaluateScript(script, withSourceURL: url)
|
|
102
|
+
} else {
|
|
103
|
+
result = context.evaluateScript(script)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Force microtask drain after evaluation.
|
|
107
|
+
context.evaluateScript("void 0;")
|
|
108
|
+
|
|
109
|
+
completion?(result)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/// Evaluate a script synchronously. MUST only be called from the JS queue.
|
|
114
|
+
@discardableResult
|
|
115
|
+
public func evaluateScriptSync(_ script: String, sourceURL: String? = nil) -> JSValue? {
|
|
116
|
+
dispatchPrecondition(condition: .onQueue(jsQueue))
|
|
117
|
+
guard let context = context else { return nil }
|
|
118
|
+
|
|
119
|
+
let result: JSValue?
|
|
120
|
+
if let sourceURL = sourceURL, let url = URL(string: sourceURL) {
|
|
121
|
+
result = context.evaluateScript(script, withSourceURL: url)
|
|
122
|
+
} else {
|
|
123
|
+
result = context.evaluateScript(script)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
context.evaluateScript("void 0;")
|
|
127
|
+
return result
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// MARK: - Function Calls
|
|
131
|
+
|
|
132
|
+
/// Call a global JS function by name with arguments. Runs on the JS queue.
|
|
133
|
+
public func callFunction(_ name: String, withArguments args: [Any], completion: ((JSValue?) -> Void)? = nil) {
|
|
134
|
+
jsQueue.async { [weak self] in
|
|
135
|
+
guard let self = self, let context = self.context else {
|
|
136
|
+
completion?(nil)
|
|
137
|
+
return
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let function = context.objectForKeyedSubscript(name)
|
|
141
|
+
guard let fn = function, !fn.isUndefined else {
|
|
142
|
+
NSLog("[VueNative macOS] Warning: JS function '\(name)' not found")
|
|
143
|
+
completion?(nil)
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let result = fn.call(withArguments: args)
|
|
148
|
+
context.evaluateScript("void 0;")
|
|
149
|
+
|
|
150
|
+
completion?(result)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/// Call a global JS function synchronously. MUST only be called from the JS queue.
|
|
155
|
+
@discardableResult
|
|
156
|
+
public func callFunctionSync(_ name: String, withArguments args: [Any]) -> JSValue? {
|
|
157
|
+
dispatchPrecondition(condition: .onQueue(jsQueue))
|
|
158
|
+
guard let context = context else { return nil }
|
|
159
|
+
|
|
160
|
+
let function = context.objectForKeyedSubscript(name)
|
|
161
|
+
guard let fn = function, !fn.isUndefined else {
|
|
162
|
+
NSLog("[VueNative macOS] Warning: JS function '\(name)' not found")
|
|
163
|
+
return nil
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let result = fn.call(withArguments: args)
|
|
167
|
+
context.evaluateScript("void 0;")
|
|
168
|
+
return result
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// MARK: - Function Registration
|
|
172
|
+
|
|
173
|
+
/// Register a Swift function as a global JS function.
|
|
174
|
+
public func registerFunction(_ name: String, block: @escaping @convention(block) (JSValue) -> Void) {
|
|
175
|
+
jsQueue.async { [weak self] in
|
|
176
|
+
guard let self = self, let context = self.context else { return }
|
|
177
|
+
let wrappedBlock: @convention(block) (JSValue) -> Void = { [weak self] value in
|
|
178
|
+
_ = self
|
|
179
|
+
block(value)
|
|
180
|
+
}
|
|
181
|
+
context.setObject(wrappedBlock, forKeyedSubscript: name as NSString)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// MARK: - Bundle Loading
|
|
186
|
+
|
|
187
|
+
/// Load a JS application bundle from the given source.
|
|
188
|
+
public func loadBundle(source: BundleSource, completion: ((Bool) -> Void)? = nil) {
|
|
189
|
+
jsQueue.async { [weak self] in
|
|
190
|
+
guard let self = self, self.context != nil else {
|
|
191
|
+
completion?(false)
|
|
192
|
+
return
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
switch source {
|
|
196
|
+
case .embedded(let name):
|
|
197
|
+
self.loadEmbeddedBundle(name: name, completion: completion)
|
|
198
|
+
case .devServer(let url):
|
|
199
|
+
self.loadDevServerBundle(url: url, completion: completion)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// MARK: - Private: Bundle Loading
|
|
205
|
+
|
|
206
|
+
private func loadEmbeddedBundle(name: String, completion: ((Bool) -> Void)?) {
|
|
207
|
+
let bundleName: String
|
|
208
|
+
let bundleExtension: String
|
|
209
|
+
|
|
210
|
+
if name.contains(".") {
|
|
211
|
+
let parts = name.split(separator: ".", maxSplits: 1)
|
|
212
|
+
bundleName = String(parts[0])
|
|
213
|
+
bundleExtension = String(parts[1])
|
|
214
|
+
} else {
|
|
215
|
+
bundleName = name
|
|
216
|
+
bundleExtension = "js"
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
var scriptURL: URL?
|
|
220
|
+
|
|
221
|
+
if let url = Bundle.main.url(forResource: bundleName, withExtension: bundleExtension) {
|
|
222
|
+
scriptURL = url
|
|
223
|
+
} else {
|
|
224
|
+
#if SWIFT_PACKAGE
|
|
225
|
+
if let url = Bundle.module.url(forResource: bundleName, withExtension: bundleExtension) {
|
|
226
|
+
scriptURL = url
|
|
227
|
+
}
|
|
228
|
+
#endif
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
guard let url = scriptURL else {
|
|
232
|
+
NSLog("[VueNative macOS] Error: Bundle '\(name)' not found in app resources")
|
|
233
|
+
completion?(false)
|
|
234
|
+
return
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
do {
|
|
238
|
+
let script = try String(contentsOf: url, encoding: .utf8)
|
|
239
|
+
NSLog("[VueNative macOS] Loading bundle: \(name) (\(script.count) bytes)")
|
|
240
|
+
self.context.evaluateScript(script, withSourceURL: url)
|
|
241
|
+
self.context.evaluateScript("void 0;")
|
|
242
|
+
NSLog("[VueNative macOS] Bundle loaded successfully")
|
|
243
|
+
completion?(true)
|
|
244
|
+
} catch {
|
|
245
|
+
NSLog("[VueNative macOS] Error loading bundle '\(name)': \(error.localizedDescription)")
|
|
246
|
+
completion?(false)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private func loadDevServerBundle(url: URL, completion: ((Bool) -> Void)?) {
|
|
251
|
+
let task = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
|
|
252
|
+
guard let self = self else {
|
|
253
|
+
completion?(false)
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
self.jsQueue.async { [weak self] in
|
|
258
|
+
guard let self = self, self.context != nil else {
|
|
259
|
+
completion?(false)
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if let error = error {
|
|
264
|
+
NSLog("[VueNative macOS] Dev server error: \(error.localizedDescription)")
|
|
265
|
+
completion?(false)
|
|
266
|
+
return
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
guard let data = data, let script = String(data: data, encoding: .utf8) else {
|
|
270
|
+
NSLog("[VueNative macOS] Dev server returned invalid data")
|
|
271
|
+
completion?(false)
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
NSLog("[VueNative macOS] Loading dev bundle from \(url) (\(script.count) bytes)")
|
|
276
|
+
self.context.evaluateScript(script, withSourceURL: url)
|
|
277
|
+
self.context.evaluateScript("void 0;")
|
|
278
|
+
NSLog("[VueNative macOS] Dev bundle loaded successfully")
|
|
279
|
+
completion?(true)
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
task.resume()
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// MARK: - Hot Reload
|
|
286
|
+
|
|
287
|
+
/// Reload the runtime with a new JavaScript bundle string.
|
|
288
|
+
public func reload(bundle: String, completion: ((Bool) -> Void)? = nil) {
|
|
289
|
+
jsQueue.async { [weak self] in
|
|
290
|
+
guard let self = self else {
|
|
291
|
+
completion?(false)
|
|
292
|
+
return
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
NSLog("[VueNative macOS] Hot reload: tearing down old context...")
|
|
296
|
+
|
|
297
|
+
if let teardown = self.context?.objectForKeyedSubscript("__VN_teardown"),
|
|
298
|
+
!teardown.isUndefined {
|
|
299
|
+
teardown.call(withArguments: [])
|
|
300
|
+
self.context?.evaluateScript("void 0;")
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
JSPolyfills.reset()
|
|
304
|
+
|
|
305
|
+
self.context = JSContext()
|
|
306
|
+
self.context.exceptionHandler = { [weak self] _, exception in
|
|
307
|
+
guard let exception = exception else { return }
|
|
308
|
+
let message = exception.toString() ?? "Unknown JS error"
|
|
309
|
+
let line = exception.objectForKeyedSubscript("line")?.toInt32() ?? 0
|
|
310
|
+
let stack = exception.objectForKeyedSubscript("stack")?.toString() ?? ""
|
|
311
|
+
NSLog("[VueNative macOS JS Error] \(message) at line \(line)")
|
|
312
|
+
#if DEBUG
|
|
313
|
+
let fullMessage = stack.isEmpty ? message : "\(message)\n\n\(stack)"
|
|
314
|
+
ErrorOverlayView.show(error: fullMessage)
|
|
315
|
+
#endif
|
|
316
|
+
_ = self
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
self.context.evaluateScript("var globalThis = this;")
|
|
320
|
+
JSPolyfills.register(in: self)
|
|
321
|
+
|
|
322
|
+
NSLog("[VueNative macOS] Hot reload: evaluating new bundle (\(bundle.count) bytes)...")
|
|
323
|
+
self.context.evaluateScript(bundle)
|
|
324
|
+
if let exception = self.context.exception {
|
|
325
|
+
NSLog("[VueNative macOS] Hot reload bundle error: %@", exception.toString() ?? "unknown")
|
|
326
|
+
self.context.exception = nil
|
|
327
|
+
completion?(false)
|
|
328
|
+
return
|
|
329
|
+
}
|
|
330
|
+
self.context.evaluateScript("void 0;")
|
|
331
|
+
NSLog("[VueNative macOS] Hot reload: complete")
|
|
332
|
+
|
|
333
|
+
completion?(true)
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// MARK: - Teardown
|
|
338
|
+
|
|
339
|
+
public func invalidate() {
|
|
340
|
+
jsQueue.async { [weak self] in
|
|
341
|
+
guard let self = self else { return }
|
|
342
|
+
self.context = nil
|
|
343
|
+
self.isInitialized = false
|
|
344
|
+
NSLog("[VueNative macOS] JS runtime invalidated")
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|