本文记录把 react-native-url-polyfill(WHATWG URL 标准实现)适配到 HarmonyOS 的完整过程。

这个库有个特点:它不需要做原生适配。但"不需要适配"本身就是个需要被证明的结论——而且证明的难点不在"它能不能跑",而在"它跑得对不对"。URL 解析有一份所有人都认的标准语料,这次就靠它把结论钉死了。

在这里插入图片描述


一、先说结论

项结果
上游最新版4.0.0(核对 npm registry 的 gitHead,与交付包 spec.json 记的基线 commit 完全一致)
是否需要原生适配不需要——没有 harmony/、没有 android/、没有 ios/,也没有自己的原生模块
是否需要 HAR / 权限 / ohpm 接线都不需要
依赖无(上游 4.0.0 已把 URL 实现打包进 js/URL.js,20,008 字节)
与 npm 上游的差异零内容改动(逐文件 SHA256 核对,唯一差异是 git checkout 的 CRLF)
自动链接信号linked 9 libraries, skipped 1 libraries —— 计数未增加,库被正确跳过
编译assembleHap 6 分 34 秒;HAP 80,867,224 → 81,260,441 字节(+393,217 ≈ 384 KB)
设备侧断言✅ 35 / 35 全部通过
WPT 官方一致性语料1580 条用例,通过 1538,失败 42;42 条全部是上游自己声明的已知偏差,未预期偏差 0
跨引擎一致性✅ 同一份测量代码跑 PC(V8)与设备(Hermes),失败集合差集为 0
同机对照鸿蒙自带 URL 只过 234 / 1580,这个库过 1538 / 1580

一句话结论:它可以直接用,不需要鸿蒙原生代码;它带来的是"从 234 条到 1538 条"的一致性提升——因为鸿蒙平台自带的 URL 是存在但残缺的。


二、判定过程:三步判断一个 RN 库要不要鸿蒙原生适配

判断一个库要不要做原生适配,我固定走三步:

步做法这个库的结果
①npm view <包名> harmony --json,看有没有 harmony.autolinking没有
②仓库里有没有 harmony/ 目录(以及 android/、ios/)都没有
③代码里有没有 NativeModules / Platform.OS / requireNativeComponent⚠️ 有,3 处

第 ① ② 步都指向"纯 JS 库",但第 ③ 步命中了。这时候不能直接下结论——第 ③ 步查到的是"信号",不是"判决"。要接着问一句:

它读的那些平台 API,鸿蒙侧有没有?

把三处平台引用摊开看:

文件平台 API用途鸿蒙上是否可用
js/URL.jsNativeModules.BlobModule只为 URL.createObjectURL 拼 blob uri✅ 存在(实测)
auto.jsPlatform.OSif (Platform.OS !== 'web') setupURLPolyfill()✅ harmony
js/ios10Fix.jsPlatform.Version、Platform.OS模块级副作用:iOS 10 上补 ArrayBuffer.prototype.byteLength✅ 不抛错

三个都用得上,三个鸿蒙侧都已经有。 所以结论是"不需要原生适配",而不是"它不碰平台"。

这个区分很重要:“纯 JS 库"不等于"零平台耦合”。 判据不是"有没有 platform 代码",而是"它依赖的平台能力鸿蒙侧是否具备"。前者会误判,后者才是真问题。

顺带一个细节:js/ios10Fix.js 是在 index.js 顶部被 import 的,也就是说只要 import 这个库,这段模块级代码就会执行(读 Platform.Version 后判断 iOS 10)。它在鸿蒙上跑过、没抛错——这一点后来单独写成了断言。


三、这个交付包长什么样:与 npm 上游逐字节一致

既然不做原生适配,那"鸿蒙版"到底改了什么?答案是:实现文件一行没改。

核对方法:拿交付仓库和 react-native-url-polyfill@4.0.0 的 npm tarball(12,696 字节,11 个文件)逐文件比 SHA256。

文件与 npm 上游
js/URL.js(20,008 字节,SHA256 758313FF…)逐字节一致
js/URLSearchParams.js逐字节一致
index.js / auto.js / index.d.ts / js/ios10Fix.js / LICENSE内容一致,差异仅 CRLF vs LF
package.json交付方改过(加了 files、把 repository 指向 AtomGit 等)
spec.json / 两个 README / 代码检查报告 / __tests__ / tsconfig.json交付方新增

第一次比 SHA256 时,index.js、auto.js、LICENSE 这几个哈希不一样,看起来像被改过。但把两边的行做 diff,一行都不差。真正的原因在字节层:

文件本地 CR 计数npm 包 CR 计数文件行数
index.js13013
js/ios10Fix.js24024
LICENSE21021

差值恰好等于行数——是 git checkout 在 Windows 上把 LF 转成了 CRLF,不是内容改动。js/URL.js 是单行文件(19,998 字符一行),没有换行可转,所以它的哈希天然一致。

教训:跨平台比对文件时,先排除换行符再下"被改过"的结论。SHA256 不一致只是"字节不同",不等于"内容不同";用"去掉 CR 后逐字符比较"才能确证。这次差点把 CRLF 误判成交付方改了上游代码。

交付仓库本身也是干净的(git status 无输出),TAG 4.0.0-ohos-1.0.0 就是唯一那个 commit。

3.1 交付包的工程质量

做得好的:

  • spec.json 里 upstream 和 upstreamCommit 两样都记了,而且 upstreamCommit 与 npm 4.0.0 的 gitHead 完全对得上——可追溯性是完整的;
  • spec.json 明写 implementation: pure JavaScript; no native module or HAR required,结论和实测一致;
  • 契约测试真的 import 了库并调用了方法(不是断言字面量那种怎么跑都会过的测试);
  • README 主动声明了限制:“主机名不支持非 ASCII Unicode 规范化”——这条后来被实测复现了。

发现一处缺陷(如实记录,未改库代码):

交付包声明的 npm test 在纯净检出下会直接失败。

package.json 里写的是 "test": "node --test __tests__/*.test.mjs",而测试文件 → js/URL.js → import {NativeModules} from 'react-native'。包里没有 dependencies,react-native 只出现在 peerDependencies。纯净检出没有 node_modules,Node 直接报:

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'react-native'
  imported from ...\js\URL.js
✖ __tests__\url.test.mjs
ℹ pass 0   ℹ fail 1

也就是说:这份契约测试只在"宿主工程内"才跑得通。 我在 Node 侧放了一个只导出 NativeModules / Platform 的 shim 之后测试才通过——说明失败原因是解析不到 react-native,不是测试本身写错了。

修复方向三选一:① devDependencies 里加 react-native;② 测试前注入一个 NativeModules 桩;③ 让 js/URL.js 对 NativeModules 的读取失败降级(try/catch),使 createObjectURL 以外的功能不依赖它。

另有可补之处:交付包没有自带 WPT 语料,而上游 4.0.0 是自带的(js/__tests__/wpt/)。它声明的契约测试是 2 个测试、约 10 条断言;上游自己那套是 1580 条。覆盖率差了几个量级——这个库恰恰是最适合用标准语料验的一类。


四、接入宿主:零原生接线,外加四处要注意的地方

纯 JS 库的接法比带原生实现的库简单得多,但有四处值得记。

1. 依赖用 file: 装

"react-native-url-polyfill": "file:../react-native-url-polyfill"

2. metro.config.js 的 watchFolders 必须加它的真实目录

file: 装进来是junction,不是真目录,Metro 只跟着 watchFolders 找源码。少了这一行,编译能过、但 bundle 里根本没有这个库:

watchFolders: [
  // …
  path.resolve(__dirname, '../react-native-url-polyfill'),
],

3. 不要动 harmony/entry/oh-package.json5

纯 JS 库不需要 HAR。这次刻意没碰它,而且专门确认了自动链接的计数没有增加:

info updated 4 file(s), linked 9 libraries, skipped 1 libraries

"linked 的计数不因纯 JS 库增加"是判断它真的不需要原生接线的信号。 如果计数涨了,说明要么库不是纯 JS,要么接线方式有问题。

另外,Metro 重定向清单(Redirected imports to N harmony-specific third-party package(s))里也不该出现纯 JS 库——那个清单是"鸿蒙变体重定向",纯 JS 库没有变体可重定向。

4. 本页额外加了一行 sourceExts

为了让 PC 端和设备端跑同一份测量代码,把测量模块写成了 .mjs。Metro 默认把 mjs 放在 additionalExts 而不是 sourceExts 里,所以显式加了一次:

resolver: {
  sourceExts: ['js', 'jsx', 'json', 'ts', 'tsx', 'cjs', 'mjs'],
  // …
}

这一行只跟本次的测量方式有关,业务接入不需要。


五、构建与运行

npm install
node_modules\.bin\react-native link-harmony        # linked 9 libraries, skipped 1 libraries
cd harmony && ohpm install --all && cd ..
npm run dev                                        # bundle
cd harmony && hvigorw --mode module -p product=default -p module=entry@default assembleHap --no-daemon
项数值
首次 assembleHap6 分 34 秒
二次重编(改了一条断言)6 分 28 秒
HAP 变化80,867,224 → 81,260,441 字节(+393,217 ≈ 384 KB)
bundle 产物bundle.harmony.js 6,248,387 字节
Metro 重定向清单里没有这个库(纯 JS,符合预期)
原生注册日志无(它没有原生模块,不该有 TM created 这种日志)

384 KB 的构成要拆开说:库本身只有约 21 KB;剩下约 360 KB 是我为了让验证可信而打进 bundle 的 WPT 官方语料(urltestdata.json 228 KB + setters_tests.json 82 KB + 豁免清单与 PC 基线约 9 KB)。业务接入不会带这些。别把测试语料的体积算到这个库头上。

这里还有个对比值得留意:这个库的编译耗时和之前那些带原生实现的库是同一个量级(6 分多)。也就是说这 6 分钟几乎全是 RNOH 工程本身的 ABI / CMake 开销,跟接进来的是纯 JS 库还是原生库基本无关。加一个纯 JS 库省下的是"原生接线与调试"的时间,不是编译时间。


六、验证设计:URL 一致性怎么验才可信

URL 解析是确定性输出——同样的输入必须得到同样的输出。这类库不能只验"调用没报错",要上已知值断言。这次的三层设计如下。

6.1 第一层:找到标准语料,而不是自己编用例

react-native-url-polyfill 的上游 4.0.0 仓库自带 WPT 官方语料(js/__tests__/wpt/)。WPT(Web Platform Tests)是浏览器 URL 实现共同遵守的一致性测试集,属于最高一档的"标准文档向量"——任何人都能拿去核对。语料构成:

文件内容计入用例
urltestdata.json1004 项(含字符串注释行),其中 891 项带输入:267 条期望失败 + 624 条期望成功构造器用例 891 + origin 用例 411 = 1302
setters_tests.json顶层 11 个键,其中 comment 键是 20 行前言文本(不是用例),其余 10 个键共 278 条278
合计 1580

用多少条自造用例都换不来"这 1580 条是标准"的分量。

6.2 第二层:把"上游已声明的偏差"和"未预期偏差"分开

这一层才是关键。 上游仓库里有一份 exceptions.json——上游自己承认"这些 WPT 用例我不合规",共 42 条。

如果没有这份清单,我跑出"42 条失败"就只能写"有 42 条不符合标准",读者没法判断严重程度。有了它,结论可以精确到:

上游 exceptions.json 声明 42 条已知偏差
  ├ 本次确实失败且已被上游声明:42
  ├ 未预期失败              :0
  └ 声明了但本次通过(过时)  :0

零未预期、零过时——意思是:这个实现的偏差恰好就是它自己声明的那些,不多不少。这比"通过率 97.3%"这种数字有力得多。

而且这个分类要求用例命名精确对齐 WPT 的测试名,所以我把测量代码按 WPT 的文件划分来组织:url-constructor 的字段(不含 origin)和 url-origin 的 origin 分成两个独立用例——否则一个因 href 失败的用例会"吃掉"它的 origin 失败,分类就错了。

6.3 第三层:独立 oracle —— 但不能当基准

我用 Node 原生 WHATWG URL 跑了同一份语料。它是与这份 JS 完全不同的实现(V8 / Ada 原生),本意是"确认 WPT 的期望值本身可达成的"。

结果出了一个反转,值得单独讲。


七、PC 端与设备端跑同一份测量代码:跨引擎一致性

纯 JS 库在鸿蒙上最大的风险不是"跑不起来",而是"在 Hermes 上跑得跟别处不一样"。要证明这件事,光在设备上跑一遍不够——得有个对照。

做法是让 PC 和设备用同一个文件:

  • 测量模块 wptUrlCorpus.mjs 是纯 ESM、不依赖 React 也不依赖 RN;
  • PC:node wpt/pc-run.mjs → import 上游的 js/URL.js 跑语料(Node 需要能解析 react-native,故加了一个只导出 NativeModules / Platform 的 shim,库文件保持逐字节不变);
  • 设备:测试页 import {runUrlWpt} from './wptUrlCorpus.mjs',用同一份语料跑同一个实现。

两边结果:

实现环境用例总数通过失败
被测实现鸿蒙 / Hermes1580153842
同一份代码PC / Node v24.14.0 V81580153842
Node 原生 WHATWG URLPC / V81580156317
鸿蒙平台自带 URL鸿蒙 / Hermes15802341346

通过数、失败数、失败集合全都一致,差集为 0——而且这个断言是在设备上直接算的(把 PC 端基线里的失败清单打进 bundle,设备端跑完做集合差)。

"测量代码同源"比"测量结果相同"更重要。 如果 PC 和设备各写一套测量代码,那"结果一致"可能只是两套代码碰巧都对,无法归因到被测实现。为此值得付出让 Metro 支持 .mjs 的那一行配置。

耗时对照(同一份 1580 条语料):

引擎耗时
PC / V833 ms
设备 / Hermes133 ms(约 4 倍)

Hermes 比 V8 慢是预期内的(Hermes 优先启动速度与内存,不追求极致吞吐)。这里要说明的是:4 倍的差距没有带来任何行为差异——这才是鸿蒙侧真正要确认的事。

7.1 那个反转:不能拿原生实现当基准

Node 原生 URL 只过了 1563 / 1580,有 17 条不符合 WPT;而这 17 条被测实现反而全部通过:

只有被测实现失败、原生通过的:42 条(= 该实现相对原生实现的能力缺口)
只有原生失败、被测实现通过的:17 条
  Parsing: <http://a.b.c.xn--pokxncvks> without base
      不应抛错:Invalid URL
  Parsing: <http://10.0.0.xn--pokxncvks> without base
      不应抛错:Invalid URL
  Parsing: <http://a.b.c.XN--pokxncvks> without base
      不应抛错:Invalid URL
  …(6 条输入,各产生 constructor + origin 两条)

语料对这 6 条输入要求解析成功(期望 href: http://a.b.c.xn--pokxncvks/),而 Node 原生直接抛 Invalid URL。node:url.domainToUnicode('xn--pokxncvks') 返回的串里带不可见字符,说明这类标签涉及不可见码点的映射——两边对规范的理解在这一角落上不一致,而按这份 WPT 快照,是原生这边不合规。

结论:如果我把"Node 原生 URL"当成唯一基准去做逐字段比对,我会把 17 条"实现比原生更合规"误判成缺陷。

所以基准的顺序必须是:

  1. 标准语料是基准(WPT);
  2. 原生实现只是参考实现之一,它可以帮你发现差异,但不能替标准下判决。

这条经验对所有"跨平台有原生对应物"的库都成立——平台自带的实现不一定是对的,甚至不一定比第三方库更接近标准。


八、同机对照:鸿蒙自带 URL 与 polyfill 差多少

上一节说明了"要跟标准比"。但还有一类问题只有同一台设备上的并排对照能回答:鸿蒙平台自带的 URL 到底行不行?

平台自带 URL 是存在的:

鸿蒙自带 URL 是否存在 = true
鸿蒙自带 URLSearchParams 是否存在 = true

但用同一份语料一量:

实现通过 / 总数耗时
鸿蒙平台自带 URL234 / 158024 ms
react-native-url-polyfill1538 / 1580133 ms

自带 URL 的首个失败样例就很说明问题:

用例:Parsing: <http://example\t.\norg> against <http://example.org/foo/bar>
期望:http://example.org/
实际:http://example.org/foo/bar/http://example\t.\norg

它把 base 当字符串拼接,根本没有相对 URL 解析——注意实际结果里,base 和 input 被直接连在了一起。这类"存在但残缺"的实现,比"完全不存在"更危险:typeof URL === 'function' 会让调用方以为可以放心用。

这也正面回答了这个库在鸿蒙上的价值:它不是"补一个缺失的东西",而是"把一个 234 分的实现换成 1538 分的实现"。 在端上拼 URL、解析 query、处理相对路径、做签名拼接这些场景里,这个差别是实打实的。


九、实测发现与已知限制

9.1 平台耦合点实测

观测项实测值
Platform.OSharmony
Platform.VersionOpenHarmony-7.0.0.32(Beta2)
JS 引擎typeof HermesInternal === 'object'
NativeModules.BlobModule 是否存在true
BlobModule.getConstants() 的键BLOB_URI_HOST, BLOB_URI_SCHEME
BLOB_URI_SCHEME / BLOB_URI_HOSTblob / null
URL.createObjectURL({data:{blobId:'demo',offset:0,size:3},size:3})blob:demo?offset=0&size=3
URL.revokeObjectURL('blob:x')undefined(空实现,与上游一致)
URL.canParse / URL.parse / URLSearchParams.prototype.size都存在

NativeModules.BlobModule 在鸿蒙上存在,所以 createObjectURL 走的是正常分支。我另外在 PC 端用不提供 BlobModule 的 shim 验证了另一条分支:那时 createObjectURL 会直接抛 Cannot create URL for blob!。

9.2 已声明的限制被实测复现:中文域名不转 punycode

上游为压体积把 URL 实现换成了"去掉 Unicode 映射表"的版本,代价是主机名不做非 ASCII Unicode 规范化。实测:

表达式这个库给出Node 原生给出
new URL('https://百度.中国/').host百度.中国xn--wkd006a.xn--fiqs8s
new URL('https://例え.テスト/').host例え.テストxn--r8jz45g.xn--zckzah
new URL('https://Go.com/').hostGo.comgo.com

这 42 条 WPT 偏差全部属于这一类原因(Unicode 主机名的 IDNA / UTS46 映射)。

业务上的实际影响:如果用中文域名做请求,一定要自己先转 punycode——否则送出去的就是原始 Unicode 主机名,DNS 层解析不了。反过来,路径、查询值、片段里的非 ASCII 字符是正常百分号编码的,不受这条限制影响(E 组验过:中文查询值 鸿蒙 编码为 %E9%B8%BF%E8%92%99,读回不变)。

9.3 已知限制清单

  1. 主机名不做非 ASCII Unicode 规范化(上游已声明,实测复现)——这是本库相对原生实现唯一的 42 条能力缺口,也是它换取体积的方式。
  2. createObjectURL 端到端未验证:只确认了它返回 blob:demo?offset=0&size=3 这样的 uri,没有真的把 blob uri 喂给 fetch / Image 验证能取到内容。
  3. 只在一台模拟器上验证(Pura X View,ohos-x64),没有真机。
  4. js/ios10Fix.js 的 iOS 10 分支永远不执行:鸿蒙上只验证了"这段模块级代码不抛错",无法验证它的功能正确性。
  5. WPT 语料用的是上游仓库的快照(urltestdata.json + setters_tests.json),上游还有 urlencoded-parser / idlharness 等测试文件未纳入;hermes.json 里上游也排除了一项(FormData 相关,与本库无关)。
  6. 未做真实的业务吞吐对比:只测了语料跑完耗时(Hermes 133 ms vs V8 33 ms)。
  7. 交付包缺陷:npm test 在纯净检出下失败(解析不到 react-native),见 3.1 节。与设备运行无关,未改库代码。

未发现实现层面的缺陷。 42 条偏差不是缺陷,是上游公开声明并写进 README 的取舍。


十、常见问题

Q1:这个库需要 HAR、权限或 ohpm 接线吗?

都不需要。它没有原生模块,harmony/entry/oh-package.json5 不用动,module.json5 也不用加权限。判断信号是:link-harmony 的 linked 计数不因它增加(本次输出 linked 9 libraries, skipped 1 libraries)。

Q2:react-native-url-polyfill 和 react-native-url-polyfill/auto 有什么区别?

  • auto 入口:import 'react-native-url-polyfill/auto' → 在 Platform.OS !== 'web' 时自动调用 setupURLPolyfill(),把实现装到全局 globalThis.URL / URLSearchParams。适合"想让全项目透明用上标准 URL"。
  • 库入口:import {URL} from 'react-native-url-polyfill' → 只导出实现,不动全局(ponyfill 用法)。适合"只想在局部用,不想改变全局行为"。

两种可以共存;setupURLPolyfill() 也可以手动调用。

Q3:装了之后怎么确认装上了?

调用 setupURLPolyfill() 会留一个版本标记:

import {setupURLPolyfill} from 'react-native-url-polyfill';
setupURLPolyfill();
console.log(globalThis.REACT_NATIVE_URL_POLYFILL);   // react-native-url-polyfill@4.0.0

Q4:平台自带的 URL 不是已经能用了?

能用,但只过 234 / 1580 条标准用例。最典型的问题是不支持相对 URL 解析:

new URL('/search?q=1', 'https://example.com/base')
// 平台自带:把 base 当字符串拼在后面 → https://example.com/base/search?q=1 ✗
// 这个库  :https://example.com/search?q=1                         ✓

Q5:中文域名为什么没有换成 punycode?

上游为压体积去掉了 Unicode 映射表,这是它公开声明的限制。需要中文域名时,请求前自己转一次:

// 先转 punycode 再交给 URL
const host = punycode.toASCII('百度.中国');   // xn--wkd006a.xn--fiqs8s

路径、查询值、片段里的中文不受影响,会正常做百分号编码。

Q6:既然有 42 条不符合 WPT,能不能算"适配不通过"?

不算。这 42 条正好等于上游 exceptions.json 自己声明的 42 条,零未预期、零过时——也就是说这个实现的偏差范围是被作者完整掌握并公开的,而且同类原因(Unicode 主机名)在 README 里也写了。

真正需要警惕的是"未预期偏差":如果跑出 43 条,那一条才是要查的。

Q7:URL.createObjectURL 在鸿蒙上能用吗?

它依赖 NativeModules.BlobModule。实测鸿蒙上 BlobModule 存在(BLOB_URI_SCHEME = blob),所以能返回 blob: 开头的 uri。但我没有做端到端验证(没真的用这个 uri 去取 Blob 内容),涉及 Blob 下载的场景建议自己补一轮。

Q8:这个库会跟别的库抢全局 URL 吗?

用 auto 入口或手动 setupURLPolyfill() 时,它会覆盖全局 URL / URLSearchParams。如果项目里还有别的库也改全局 URL,就有顺序问题——这时建议改用库入口(ponyfill),只在需要的地方 import。

Q9:怎么自己把这一轮验证跑一遍?

# PC 端复算(同一份测量代码)
node wpt/pc-run.mjs

# 设备端
hdc shell aa force-stop com.rnoh084.demo
hdc shell aa start -b com.rnoh084.demo -a EntryAbility --ps rnAppKey UrlPolyfillTestApp
# 界面上点「跑全部」
hdc shell "hilog -x | grep urlpolyfill-test" | Select-String '汇总|✗'

小结

react-native-url-polyfill 是个不需要原生适配的库:没有 harmony/ 目录,实现文件与 npm 上游逐字节一致,接进宿主只需要改 package.json、metro.config.js、index.js 三处,自动链接的计数都不会增加。

但这次真正花时间的不是"接进来",而是"证明它是对的"。几点体会:

  1. “不需要适配"要证明,而且证明的落点是"对不对”,不是"能不能跑"。 代码量小、接口简单,都不等于验证简单。

  2. 找标准语料,别自己编用例。 WPT 那 1580 条是浏览器共同遵守的一致性测试集,用它是把"我觉得对"换成"标准认为对"。而且上游自己带了这份语料,先翻仓库再动手写测试。

  3. "上游自己声明的偏差"是一份礼物。 有了 exceptions.json,42 条失败才能被精确切成"已知 42 / 未预期 0";没有它,这个数字既没法解释也不可信。遇到带豁免清单的交付包或上游,一定要拿来用。

  4. 不能拿原生实现当基准。 Node 原生 URL 有 17 条不符合 WPT,反倒被测实现全过。用原生做 oracle 会把"更合规"误判成"有缺陷"。基准只能是标准;原生只是参考实现之一。

  5. 测量代码同源,比测量结果相同更重要。 PC 与设备共用同一个 .mjs,“结果一致"才能归因到被测实现,而不是"两套测量代码碰巧都对”。

  6. "存在但残缺"比"不存在"更危险。 鸿蒙自带 URL 是存在的、typeof 是 function——只断言"存在"就通过了,实际只过 234/1580。同机对照能一刀切开这种假象,而这台设备上唯一能跟它对量的,就是同一份标准语料。

关于交付包:它的可追溯性做得不错(upstream 与 upstreamCommit 都在,且与 npm 的 gitHead 对得上),契约测试也是真的在调用库。不足有两点:npm test 在纯净检出下会失败(解析不到 react-native),以及没有把上游自带的 WPT 语料收进来——对这类"有标准可依"的库,这是最值得补的一块。

在这里插入图片描述
在这里插入图片描述


本篇用到的库

项内容
三方库react-native-volume-control(上游 1.0.1 的鸿蒙适配版)
适配仓库https://atomgit.com/oh-react-native/react-native-volume-control
适配 TAG1.0.1-ohos-1.0.0
ohpm 包名@react-native-ohos/react-native-volume-control
HARharmony/volume_control.har(3,756 字节)
原生模块名VolumeControl(ArkTS TurboModule,日志标签 #RNOH_ARK)
是否需要权限不需要(媒体音量读写不要求声明权限)
上游仓库https://github.com/rtmalone/react-native-volume-control(基线 commit 2915b27068fe67c7a835da2f136fa58d9b7c6cae;npm 元数据声明 ISC,随包 LICENSE 为 MIT)
宿主工程RNOH084Demo(测试页 rnAppKey = VolumeControlTestApp)

接入方式(纯 JS,零原生接线):

// package.json
"react-native-url-polyfill": "file:../react-native-url-polyfill"
// metro.config.js —— file: 装进来是 junction,必须让 Metro 找得到源码
watchFolders: [
  path.resolve(__dirname, '../react-native-url-polyfill'),
],
// 用法一:ponyfill,不动全局
import {URL, URLSearchParams} from 'react-native-url-polyfill';

// 用法二:装到全局(auto 入口)
import 'react-native-url-polyfill/auto';

// 用法三:手动装到全局
import {setupURLPolyfill} from 'react-native-url-polyfill';
setupURLPolyfill();
console.log(globalThis.REACT_NATIVE_URL_POLYFILL);   // react-native-url-polyfill@4.0.0

// 典型用法:相对 URL + 中文查询值
const u = new URL('/search?q=鸿蒙', 'https://example.com/base');
u.toString();               // https://example.com/search?q=%E9%B8%BF%E8%92%99
u.origin;                   // https://example.com
u.searchParams.get('q');    // 鸿蒙
u.searchParams.append('page', '2');

// 安全解析用户输入
URL.canParse('https://example.com');   // true
URL.canParse('not a URL');             // false
# 换页启动测试页(force-stop 不能省,换页参数只在冷启动生效)
hdc shell aa force-stop com.rnoh084.demo
hdc shell aa start -b com.rnoh084.demo -a EntryAbility --ps rnAppKey UrlPolyfillTestApp

验证环境

项版本
React Native0.84.1
React19.2.3
RNOH(npm / ohpm)@react-native-oh/react-native-harmony / @rnoh/react-native-openharmony 0.84.3
Node.jsv24.14.0(PC 端复算用)
DevEco Studio26.0.0.621
HarmonyOS SDKAPI 26(26.0.0.32)
设备HarmonyOS 7.0.0(26.0.0) Beta2 模拟器 Pura X View(ohos-x64),Platform.Version 报 OpenHarmony-7.0.0.32(Beta2)
JS 引擎Hermes
宿主 HAP 产物entry-default-signed.hap(81.26 MB)
本次增量构建assembleHap 6 分 34 秒,HAP +393,217 字节(≈384 KB,其中约 360 KB 是测试语料)
验证规模设备侧 35 / 35 断言全部通过;WPT 官方语料 1580 条:通过 1538,失败 42(全部为上游声明项);与 PC 端失败集合差集为 0

欢迎加入 CPF-RN 鸿蒙社区:https://atomgit.com/CPF-RN

React Native for OpenHarmony 组织:https://atomgit.com/oh-react-native

RN 三方库鸿蒙适配清单:https://atomgit.com/oh-react-native/rn-ohos-adaptation-overview

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐