# Compatibility baseline

> The JavaScript and CSS floor a mini app can rely on across iOS and Android, and why the two engines differ.

Source: https://miniapp.sollar.com/reference/baseline/

---

A mini app runs in **JavaScriptCore on iOS** and **V8 on Android**. That is not a design choice
Sollar made; it is a legal one it inherited.

Apple's Guideline 2.5.6 requires that apps browsing the web *"use the appropriate WebKit framework
and WebKit JavaScript."* The Embedded Browser Engine Entitlement that would allow otherwise exists
only in the European Union, and qualifying for it requires 90% pass rates on the Web Platform Tests,
80% on Test262, a memory-safe implementation language and a 30-day CVE remediation commitment.

So the engines differ, and they will keep differing. What Sollar can do is name a floor and test
against it.

## The floor

| | Baseline |
|---|---|
| JavaScript | ECMAScript 2022 |
| CSS | Everything in Baseline "Widely available" as of 2024 |
| iOS | WKWebView on iOS 16.4+ |
| Android | Android System WebView 114+ |

Anything at or below this floor works on every device Sollar supports. Anything above needs feature
detection.

## What ES2022 gives you

Class fields and private methods, `at()`, `Object.hasOwn()`, top-level `await`, `Error.cause`,
`Array.prototype.findLast()`, RegExp match indices. Modules, `async`/`await`, optional chaining and
nullish coalescing are all far below the floor.

## Above the floor — check first

| Feature | Note |
|---|---|
| `Array.prototype.group` / `groupBy` | Shipped at different times on the two engines. Detect. |
| `Temporal` | Not on the floor. Use a library. |
| Decorators | Compile them; do not ship them raw. |
| `structuredClone` | Available, but with divergent handling of some types. |
| Web Locks | Not on iOS. |
| `showOpenFilePicker` | Chromium only. Fall back to `<input type="file">`. |
| `container-queries` | Above the floor on the oldest supported iOS. Detect. |
| `:has()` | Same. |

```js
if ('group' in Array.prototype) { /* … */ } else { /* … */ }
if (CSS.supports('selector(:has(a))')) { /* … */ }
```

Feature detection, never user-agent sniffing. The user agent inside a mini app is deliberately
uninformative, and treating it as a capability signal will produce wrong answers on both platforms.

## Known divergences

| | JavaScriptCore (iOS) | V8 (Android) |
|---|---|---|
| Stack trace format | `Error.stack` differs in shape | |
| `toLocaleString` output | ICU version differs; the *string* differs | |
| Regex Unicode property escapes | Both support them; edge cases differ | |
| Timer clamping in background | More aggressive on iOS | |
| Number formatting near precision limits | Differs in the last digit | |

The practical rule: **never parse a formatted string you produced with `toLocaleString`.** Format
for display, compute on the underlying value. This is the single most common source of a bug that
appears on one platform only.

## Conformance suite

```sh
sollar test --conformance
```

Runs Sollar's own suite against whichever runtime is attached — dev server, iOS simulator, Android
emulator, or a physical device. It covers the ES2022 floor, the CSS baseline, every `sollar.*`
method, and the permission paths.

**The permission tests run identically in all three environments.** Development, trial and
production share one authorisation code path; what changes between environments is data and
endpoints, never the permission check. Environment-divergent permission behaviour is one of the six
vulnerability categories this platform is designed against — see [Security model](/platform/security-model/).

## Version policy

- The floor rises **at most once a year**, announced at least two release cycles ahead.
- A raised floor never breaks an installed mini app; it changes what new submissions may assume.
- Removing anything from the bridge requires a major version and a deprecation window.

## Secure context

Mini apps run at a synthetic origin over `https`, so they are secure contexts and `crypto.subtle`,
service workers and the rest are available.

> **CAUTION**
On iOS this depends on a custom scheme served through `WKURLSchemeHandler` being treated as a secure
context. This is verified per release and is tracked as an open risk in the internal specification —
if it fails on a future iOS version, `crypto.subtle` becomes unavailable inside mini apps and the
encrypted-storage design changes. Do not build a design whose only failure mode is this assumption
holding.
