bao-servo 0.5.8

A component of the servo web-engine.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! Servo, the mighty web browser engine from the future.
//!
//! This crate wires all of Servo's components together as type [`Servo`], along with
//! a Webview implementation, [`WebView`], to create a working web engine.
//!
//! To embed Servo in your application, you need to:
//! 1) Create an instance of a type that implements the [`EventLoopWaker`] trait.
//!    This trait allows Servo to integrate with your application's event loop. Your
//!    [`EventLoopWaker::wake`] implementation needs to ensure that
//!    [`Servo::spin_event_loop`] is eventually called to let Servo process user input,
//!    network events etc.
//! 2) Create a [`Servo`] instance using the [`ServoBuilder`] type. You can optionally
//!    register a [`ServoDelegate`] implementation to subscribe to notifications about
//!    events and customize certain behaviours.
//! 3) Create an instance of a type that implements the [`RenderingContext`] trait.
//!    Note: You can either use one of the existing types in this crate (such as
//!    [`WindowRenderingContext`], [`OffscreenRenderingContext`] or [`SoftwareRenderingContext`])
//!    or provide a custom implementation.
//! 4) For each [`WebView`] in your application, create a [`WebViewBuilder`] by passing
//!    it the [`RenderingContext`] and [`Servo`] instance, and then configure the
//!    builder and use it to create a [`WebView`] instance. The builder must be provided
//!    with a [`WebViewDelegate`] implementation which, at a minimum, should handle
//!    [`WebViewDelegate::notify_new_frame_ready`] by calling [`WebView::paint`]
//!    and presenting the rendered page using [`RenderingContext::present`]. Refer to the
//!    documentation of the [`WebView`] type to learn more about the relation
//!    between a [`WebView`] and its [`RenderingContext`].
//! 5) Run the application's event loop. Your application's event handlers need to
//!    forward input events for a particular [`WebView`] using one of the `notify_*` methods
//!    on that [`WebView`] instance. For example, to forward a mouse event to a [`WebView`],
//!    call the [`WebView::notify_input_event`]. You can also invoke methods on a [`WebView`]
//!    to request certain actions. For instance, the [`WebView::load`] method requests that
//!    Servo navigate to a new page. In both cases, the calls to the [`WebView`] methods
//!    must be followed by calls to [`Servo::spin_event_loop`] to allow Servo to process
//!    those requests.
//!
//! For a minimal working example, refer to the [`winit_minimal`] code.
//!
//! [`winit_minimal`]: https://github.com/servo/servo/blob/main/components/servo/examples/winit_minimal.rs

mod clipboard_delegate;
#[cfg(feature = "gamepad")]
mod gamepad_delegate;
#[cfg(feature = "media-gstreamer")]
mod gstreamer_plugins;
mod javascript_evaluator;
mod network_manager;
mod proxies;
mod responders;
mod servo;
mod servo_delegate;
mod site_data_manager;
mod user_content_manager;
mod webview;
mod webview_delegate;

// These are Servo's public exports. Everything (apart from a couple exceptions below)
// should be exported at the root. See <https://github.com/servo/servo/issues/18475>.
pub use accesskit;
pub use embedder_traits::user_contents::UserScript;
pub use embedder_traits::{submit_resource_reader, *};
pub use image::RgbaImage;
pub use keyboard_types::{
    Code, CompositionEvent, CompositionState, Key, KeyState, Location, Modifiers, NamedKey,
};
pub use media::{
    GlApi as MediaGlApi, GlContext as MediaGlContext, NativeDisplay as MediaNativeDisplay,
};
pub use net::image_cache::should_panic_hook_suppress_termination;
pub use net_traits::CookieSource;
// This API should probably not be exposed in this way. Instead there should be a fully
// fleshed out public domains API if we want to expose it.
pub use net_traits::pub_domains::is_reg_domain;
pub use paint::WebRenderDebugOption;
pub use paint_api::rendering_context::{
    OffscreenRenderingContext, RenderingContext, SoftwareRenderingContext, WindowRenderingContext,
};
// Expose our profile traits for servoshell, so we can instrument code there, but don't
// add it as an official API.
#[doc(hidden)]
pub use profile_traits;
// This should be replaced with an API on ServoBuilder.
// See <https://github.com/servo/servo/issues/40950>.
pub use resources;
pub use servo_base::generic_channel::GenericSender;
pub use servo_base::id::WebViewId;
pub use servo_config::opts::{DiagnosticsLogging, DiagnosticsLoggingOption, Opts, OutputOptions};
pub use servo_config::prefs::{PrefValue, Preferences, UserAgentPlatform};
pub use servo_config::{opts, pref, prefs};
pub use servo_geometry::{
    DeviceIndependentIntRect, DeviceIndependentPixel, convert_rect_to_css_pixel,
};
#[doc(hidden)]
pub use servo_tracing;
pub use servo_url::ServoUrl;
pub use style::Zero;
pub use style_traits::CSSPixel;
pub use webrender_api::units::{
    DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel, DevicePoint, DeviceVector2D,
};

/// Register a callback to be executed on this WebView's ScriptThread the next
/// time `handle_evaluate_javascript` runs, before the evaluated JS executes.
///
/// The callback receives `(cx, global)` as `(*mut c_void, *mut c_void)` which
/// are actually `(*mut mozjs::jsapi::JSContext, *mut mozjs::jsapi::JSObject)`.
/// Cast them to the correct types in your callback.
///
/// This enables embedders (e.g., Bao) to register Rust host functions on
/// servo's Window global object, making them available to page JavaScript.
pub fn register_script_thread_callback(
    webview_id: WebViewId,
    callback: Box<dyn FnOnce(*mut std::ffi::c_void, *mut std::ffi::c_void) + Send>,
) {
    script::register_embedder_callback(webview_id, callback);
}

/// Register the process-global embedder event-loop pump (Bao vendor patch —
/// page-realm async fetch settlement).
///
/// Bao's page-realm `fetch` override resolves through a ConcurrentTask on the
/// ScriptThread's bao MiniEventLoop, which servo never ticks by itself. The
/// registered pump is called by `handle_msgs` on each ScriptThread right
/// after its blocking recv returns (a fetch completion wakes that recv via
/// [`bao_current_thread_wake_fn`]), with the thread's JSContext as
/// `*mut c_void` (actually `*mut mozjs::jsapi::JSContext`).
pub fn register_bao_event_loop_pump(pump: script::BaoEventLoopPump) {
    script::register_bao_event_loop_pump(pump);
}

/// Register the process-global realm-discard timer cancel (Bao vendor
/// patch — RED-1 P-A, user ruling 2026-09-10).
///
/// Same-registered-domain navigation reuses the ScriptThread and
/// eventually discards the old page realm; the registered cancel is
/// invoked from `handle_exit_pipeline_msg` (BEFORE the `window_detached`
/// gate — a detached window never reaches `clear_js_runtime`) with
/// `(cx, global)` as `*mut c_void` (actually `*mut mozjs::jsapi::JSContext`
/// / `*mut mozjs::jsapi::JSObject` — the discarded realm's global) so the
/// embedder purges the thread's bao timer registry for exactly that
/// global. Without it, the old realm's bao timers fired zombie callbacks
/// into the discarded realm forever and the raw-rooted global pinned it
/// against GC (per-nav accumulation).
pub fn register_bao_realm_discard_cancel(cancel: script::BaoRealmDiscardCancel) {
    script::register_bao_realm_discard_cancel(cancel);
}

/// Run `f` with the calling ScriptThread's script settings stack pushed for
/// `global_object`'s realm (Bao vendor patch — BCE-20260910-004, the
/// settings-stack side of the pump bridge above).
///
/// The embedder's event-loop pump fires page-realm bao timers OUTSIDE any
/// settings-stack entry; a page callback touching `location.*` getters,
/// `document.open()` or canvas origin-clean checks then dereferenced
/// `entry_global().unwrap()` on an empty stack and panicked
/// (`dom/bindings/settings_stack.rs:36`). This is servo's own "prepare to
/// run script" step (`run_a_script`), exported so the embedder can wrap its
/// JS dispatches in the same contract every servo JS entry honors. Both
/// pointers are `*mut c_void` (actually `*mut mozjs::jsapi::JSContext` /
/// `*mut mozjs::jsapi::JSObject`); null falls back to running `f` bare.
pub fn bao_run_in_script_settings(
    cx: *mut std::ffi::c_void,
    global_object: *mut std::ffi::c_void,
    f: &mut dyn FnMut(),
) {
    script::bao_run_in_script_settings(cx, global_object, f);
}

/// The current thread's wake closure, if this thread is a servo ScriptThread
/// (Bao vendor patch — the fetch side of the pump bridge above). The fetch
/// machinery captures this ON THE CREATING THREAD at fetch start and fires
/// it from its HTTPThread when a resolve lands; the closure sends a
/// `MainThreadScriptMsg::WakeUp` to the owning ScriptThread.
pub fn bao_current_thread_wake_fn() -> Option<std::sync::Arc<dyn Fn() + Send + Sync>> {
    script::bao_current_thread_wake_fn()
}

/// Register a callback to be executed on the Worker thread the next time a
/// servo-native `DedicatedWorkerGlobalScope::run_worker_scope` finishes
/// constructing the Worker global object **for `webview_id`**.
///
/// The callback receives `(cx: *mut c_void, global: *mut c_void)` which are
/// actually `(*mut mozjs::jsapi::JSContext, *mut mozjs::jsapi::JSObject)`.
///
/// Bao vendor patch (DEC-WK-001 / TASK-1: servo-native Worker path): inject
/// stealth profile inheritance, WorkerHandle lifecycle tracking, and
/// self.close()/importScripts native hooks.
/// Bao patch (per-worker association): keyed by WebViewId — a Worker scope
/// creation only drains callbacks registered for its own webview, so page-JS
/// `new Worker()` can never consume another page's queued callback.
pub fn register_worker_scope_callback(
    webview_id: WebViewId,
    callback: Box<dyn FnOnce(*mut std::ffi::c_void, *mut std::ffi::c_void) + Send>,
) {
    script::register_worker_scope_callback(webview_id, callback);
}

/// Register a callback to be executed on the Worker thread the next time a
/// servo-native worker global's WebIDL interfaces are defined **for
/// `webview_id`** — drained inside `WorkerGlobalScope::run_worker_script`
/// right after `define_all_exposed_interfaces` and before the worker script
/// runs.
///
/// The callback receives `(cx: *mut c_void, global: *mut c_void)` which are
/// actually `(*mut mozjs::jsapi::JSContext, *mut mozjs::jsapi::JSObject)`.
///
/// Bao vendor patch (REQ-BRW-004 C15, user ruling 2026-09-09): the FIRST
/// worker-scope drain point runs before the worker's interface objects
/// exist, so bao_stealth's JS prototype hooks (W1a `typeof` guards) were
/// silently skipped there. This second, later drain point lets the embedder
/// re-run its idempotent install once interfaces are defined.
pub fn register_worker_interfaces_ready_callback(
    webview_id: WebViewId,
    callback: Box<dyn FnOnce(*mut std::ffi::c_void, *mut std::ffi::c_void) + Send>,
) {
    script::register_worker_interfaces_ready_callback(webview_id, callback);
}

/// Register a per-Worker injector delivered to EVERY Dedicated Worker scope
/// created for `webview_id` (Bao vendor patch, REQ-BRW-004, user ruling
/// 2026-09-09).
///
/// Unlike the consume-once callbacks above — which only the FIRST Worker of
/// the webview drains — an injector is delivered at every Worker's scope
/// construction (first drain point, after the one-shot callbacks) and is
/// never consumed, so the SECOND and later `new Worker()` in the same page
/// receive the same embedder install (engine getters + JS hooks) instead of
/// a bare, fingerprintable Worker global. The injector receives
/// `(cx: *mut c_void, global: *mut c_void)` which are actually
/// `(*mut mozjs::jsapi::JSContext, *mut mozjs::jsapi::JSObject)` and runs on
/// each Worker thread. Registration is an upsert: one injector per webview.
pub fn register_worker_scope_injector(
    webview_id: WebViewId,
    injector: script::EmbedderWorkerInjector,
) {
    script::register_worker_scope_injector(webview_id, injector);
}

/// Register a per-Worker injector delivered at the SECOND drain point —
/// right after `define_all_exposed_interfaces` and before the worker script
/// runs — for EVERY Dedicated Worker of `webview_id` (never consumed).
///
/// Bao vendor patch (REQ-BRW-004, user ruling 2026-09-09): same per-Worker
/// delivery semantics as [`register_worker_scope_injector`], landing the
/// W1a-guarded JS prototype hooks that require defined interfaces.
pub fn register_worker_interfaces_ready_injector(
    webview_id: WebViewId,
    injector: script::EmbedderWorkerInjector,
) {
    script::register_worker_interfaces_ready_injector(webview_id, injector);
}

/// Remove every per-Worker injector registered for `webview_id` (both drain
/// phases). The embedder calls this when the page closes so a closed page's
/// injectors do not linger in the registries.
pub fn unregister_worker_injectors(webview_id: WebViewId) {
    script::unregister_worker_injectors(webview_id);
}

/// The per-Worker injector type behind
/// [`register_worker_scope_injector`] /
/// [`register_worker_interfaces_ready_injector`]: a shared closure receiving
/// `(cx: *mut c_void, global: *mut c_void)` on each Worker thread of the
/// webview it is registered for.
pub use script::EmbedderWorkerInjector;

/// Set anti-fingerprinting TLS/HTTP2 configuration for servo's network layer
/// (Bao vendor patch, REQ-STL-001: browser-level JA3/JA4 anti-fingerprinting).
///
/// When set, servo's TLS consumers (the page-network bun bridge and the
/// boringssl-backed WebSocket loader) use these
/// values for TLS cipher suite/curves/signature algorithm reordering and ALPN
/// negotiation, plus HTTP/2 connection parameters (SETTINGS frame, window
/// sizes). boringssl supports full JA3/JA4 fingerprint configuration.
pub use net::connector::StealthTlsWireConfig;

pub fn set_stealth_tls_config(config: Option<StealthTlsWireConfig>) {
    net::connector::set_stealth_tls_config(config);
}

/// Per-WebViewId stealth wire configuration (R53-A net face).
///
/// The process-global setter above stays as the identity-less fallback
/// default; keyed entries are authoritative for requests carrying
/// `target_webview_id` (page fetch/XHR egress, worker realms with their
/// owning page, SW realms stamped with the registering page), so two pages
/// with different `stealth_profile`s no longer silently cross-contaminate
/// each other's TLS/H2 wire fingerprint.
pub use net::connector::Http2Fingerprint;

pub fn set_stealth_wire_config_for_webview(
    webview_id: WebViewId,
    tls: Option<StealthTlsWireConfig>,
    h2: Option<Http2Fingerprint>,
) {
    net::connector::set_stealth_wire_config_for_webview(webview_id, tls, h2);
}

/// Drop a webview's keyed stealth wire-config entries (page close).
pub fn clear_stealth_wire_config_for_webview(webview_id: WebViewId) {
    net::connector::clear_stealth_wire_config_for_webview(webview_id);
}

/// Network event tap types + installer for embedder-side network observability
/// (Bao vendor patch, REQ-BRW-004 criterion #19 subclause ②: CDP Network
/// domain observability of SW-intercepted and regular fetches).
///
/// When a tap is installed, `main_fetch`'s request/response instrumentation
/// points forward every fetch (service-worker-mediated responses and the SW
/// realm's own sub-fetches included) to the closure. The closure runs on
/// fetch worker threads and must not block.
pub use net::http_loader::{BaoNetworkTap, BaoNetworkTapEvent};

pub fn set_network_event_tap(tap: Option<BaoNetworkTap>) {
    net::http_loader::set_network_event_tap(tap);
}

/// Webview-less `WebResourceRequested` local-verdict types + installer
/// (Bao vendor patch, BCE-20260910-002).
///
/// Upstream servo answers every `WebResourceRequested` round-trip from a
/// resident embedder main loop (`Servo::spin_event_loop`). Bao's embedder
/// is a lazy pump (PageHandle interaction APIs) and `Servo` is !Send, so a
/// fetch with `target_webview_id == None` (SW/worker realms) could park in
/// the interceptor's embedder wait forever while the owning page sat idle.
/// The embedder (bao_browser, at `BaoRuntime::new`) installs one
/// process-wide handler that the net request interceptor consults locally
/// for those requests. With no handler installed, the upstream embedder
/// round-trip is preserved unchanged; webview-owned requests always keep
/// the full round-trip.
pub use net::request_interceptor::{
    BaoWebviewlessResourceHandler, BaoWebviewlessResourceVerdict,
};

pub fn set_webviewless_resource_handler(handler: Option<BaoWebviewlessResourceHandler>) {
    net::request_interceptor::set_webviewless_resource_handler(handler);
}

/// Set anti-fingerprinting canvas noise seed and amplitude (REQ-STL-003).
/// The noise is applied at the servo rendering layer, undetectable from JS.
pub fn set_canvas_noise_seed(seed: u64, noise_amplitude: f64) {
    servo_canvas::canvas_noise::set_global_canvas_noise(seed, noise_amplitude);
}

/// Upsert one webview's canvas noise configuration (BUN-EVOLUTION R53-A
/// phase 2). The keyed entry is AUTHORITATIVE for canvases created by that
/// webview (window AND worker realms alike — identity is stamped at canvas
/// creation via `GlobalScope::egress_webview_id` and threaded to the paint
/// thread). `seed == 0` writes an explicit DISABLED entry so a stealth-free
/// page reads its canvases back byte-exact instead of inheriting another
/// page's seed through the process-global fallback (which
/// [`set_canvas_noise_seed`] still owns).
pub fn set_canvas_noise_for_webview(webview_id: WebViewId, seed: u64, noise_amplitude: f64) {
    servo_canvas::canvas_noise::set_canvas_noise_for_webview(
        webview_id,
        seed,
        noise_amplitude,
    );
}

/// Drop a webview's keyed canvas noise entry (page close; same lifecycle
/// discipline as [`clear_stealth_wire_config_for_webview`]).
pub fn clear_canvas_noise_for_webview(webview_id: WebViewId) {
    servo_canvas::canvas_noise::clear_canvas_noise_for_webview(webview_id);
}

/// Set anti-fingerprinting engine-native realm timezone policy
/// (SM-EVOLUTION #28, verdict consumed 2026-09-10 — REQ-STL identity
/// consistency).
///
/// Arms SpiderMonkey's creation-time `forceUTC_` flag on every subsequently
/// created servo realm (Window / DedicatedWorker / SharedWorker /
/// ServiceWorker — `create_global_object` is the single choke point): all
/// Date local-time computations run in UTC+0 (SM maps the flag to the real
/// IANA zone Atlantic/Reykjavik, Firefox RFP shape) instead of leaking the
/// host zone through `getTimezoneOffset` / `toString` / Intl offsets.
///
/// The flag is creation-time only (no post-creation setter): arm it BEFORE
/// the target page's pipeline realms exist (bao_browser arms it at page
/// creation). Last write wins process-wide; `false` restores upstream
/// host-derived behavior for stealth-free pages.
pub fn set_force_utc_realms(force: bool) {
    script::set_force_utc_realms(force);
}

/// Set anti-fingerprinting DOM high-resolution timestamp grid, in
/// microseconds (SM-EVOLUTION #28; 0 = upstream 10µs grid, byte-for-byte).
///
/// Every DOM high-resolution timestamp (`performance.now`, `timeOrigin`,
/// performance/resource/LCP entries) funnels through the single
/// `ToDOMHighResTimeStamp` conversion this configures — quantizing it to
/// the SAME grid the engine-native Date clamp (`JS::SetTimeResolutionUsec`,
/// armed by the embedder from the same `StealthProfile::timing` field)
/// uses, so the two time layers can never advertise different precisions
/// (the inconsistency itself is a fingerprint signal; upstream's
/// servo-specific 10µs grid is one too).
pub fn set_dom_time_precision_us(precision_us: u64) {
    script::set_dom_time_precision_us(precision_us);
}

pub use crate::clipboard_delegate::{ClipboardDelegate, StringRequest};
#[cfg(feature = "gamepad")]
pub use crate::gamepad_delegate::{
    GamepadDelegate, GamepadHapticEffectRequest, GamepadHapticEffectRequestType,
};
pub use crate::network_manager::{CacheEntry, NetworkManager};
pub use crate::servo::{Servo, ServoBuilder, run_content_process};
pub use crate::servo_delegate::{ServoDelegate, ServoError};
pub use crate::site_data_manager::{SiteData, SiteDataManager, StorageType};
pub use crate::user_content_manager::UserContentManager;
pub use crate::webview::{WebView, WebViewBuilder};
pub use crate::webview_delegate::{
    AlertDialog, AllowOrDenyRequest, AuthenticationRequest, BluetoothDeviceSelectionRequest,
    ColorPicker, ConfirmDialog, ContextMenu, CreateNewWebViewRequest, EmbedderControl, FilePicker,
    InputMethodControl, NavigationRequest, PermissionRequest, PromptDialog, SelectElement,
    SimpleDialog, WebResourceLoad, WebViewDelegate,
};

#[cfg(feature = "webxr")]
pub mod webxr {
    #[cfg(not(any(target_os = "android", target_env = "ohos")))]
    pub use webxr::glwindow::{GlWindow, GlWindowDiscovery, GlWindowMode, GlWindowRenderTarget};
    #[cfg(not(any(target_os = "android", target_env = "ohos")))]
    pub use webxr::headless::HeadlessMockDiscovery;
    #[cfg(target_os = "windows")]
    pub use webxr::openxr::{AppInfo as OpenXrAppInfo, OpenXrDiscovery};
    pub use webxr::{Discovery, MainThreadRegistry, WebXrRegistry};
}

// TODO: The protocol handler interface needs to be cleaned and simplified.
pub mod protocol_handler {
    pub use net::fetch::methods::{DoneChannel, FetchContext};
    pub use net::filemanager_thread::FILE_CHUNK_SIZE;
    pub use net::protocols::{ProtocolHandler, ProtocolRegistry};
    pub use net_traits::filemanager_thread::RelativePos;
    pub use net_traits::http_status::HttpStatus;
    pub use net_traits::request::Request;
    pub use net_traits::response::{Response, ResponseBody};
    pub use net_traits::{NetworkError, ResourceFetchTiming};

    pub use crate::webview_delegate::ProtocolHandlerRegistration;
}

// We need to reference this crate, in order for the linker not to remove it.
#[cfg(all(feature = "baked-in-resources", not(target_env = "ohos")))]
use servo_default_resources as _;