Worklets without captured variables are rejected as "Regular javascript function" when transpiled by react-native-worklets' Babel plugin
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 55/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- cpp, javascript, react-native
Hướng nghiên cứu
Start with cpp/WKTJsiWorklet.h, especially isDecoratedAsWorklet() and createWorklet(), then trace how JsiObjectWrapper::setFunctionValue() handles a function without __closure. Reproduce with the supplied Babel output: a numeric __workletHash, string __initData.code, and no closure. Done when that no-capture worklet is recognized and invoked successfully while existing captured worklets still work.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Description
When a project uses the Babel plugin from react-native-worklets (the Reanimated 4 worklets package) together with react-native-worklets-core, any 'worklet' function that does not capture any outer variables is not recognized as a worklet by worklets-core.
Calling such a function from inside another worklet that runs on a worklets-core context throws:
Regular javascript function 't' cannot be shared. Try decorating the function with the 'worklet' keyword to allow the javascript function to be used as a worklet.
('t' is just the minified function name in a release bundle.)
We hit this through react-native-filament: EntitySelector's MaterialModifier worklet calls the module-level applyMaterialParameters worklet, which captures nothing, so every model with materialParameters fails on the worklet thread.
Environment
- react-native: 0.88.0 (New Architecture, Hermes)
- react-native-worklets-core: 1.6.3
- react-native-worklets: 0.13.0 (its Babel plugin is active)
- react-native-filament: 1.9.0 (where we first saw it; 1.11.0 has the same code)
- Babel plugins:
plugins: [ ['react-native-worklets-core/plugin', { processNestedWorklets: true }], 'react-native-worklets/plugin', ]
Minimal reproduction
import { Worklets } from 'react-native-worklets-core'
// Captures nothing from the outer scope
const double = (x: number) => {
'worklet'
return x * 2
}
const context = Worklets.createContext('repro')
// The worklet passed to runAsync captures `double`
context
.runAsync(() => {
'worklet'
return double(21) // <- throws "Regular javascript function '...' cannot be shared"
})
.then(console.log)
If double captures any outer variable (so it gets a __closure), the call works.
What the transpiled code looks like
With the react-native-worklets plugin (0.13.0, and the same in the 0.14 nightlies), a worklet that captures nothing is emitted without __closure, and the hash is a number literal:
var double = function double_Factory([_worklet_123_init_data]) {
const double = function (x) { return x * 2 }
double.__workletHash = 123 // number, not string
double.__initData = _worklet_123_init_data // { code: "(function ...)" }
return double // no __closure assignment
}([_worklet_123_init_data])
The plugin only emits __closure when closureVariables.length > 0 (see plugin/index.js), so leaving it out is intended behavior there, not a bug.
Root cause
In cpp/WKTJsiWorklet.h:
isDecoratedAsWorklet()returnstrueright away only when__workletHashis a string. Otherwise it requires__closureto be present, so a numeric hash with no__closureis treated as a regular function.createWorklet()returns early when__closureisundefined/null, so even if detection passed, the worklet would not be created.
JsiObjectWrapper::setFunctionValue() then wraps the function in a host function that throws the "cannot be shared" error when called.
Suggested fix
Treat a function as a worklet when __workletHash is a number and __initData.code is a string, and use an empty closure when __closure is missing. Code generated for a worklet with no captures never reads this.__closure, so an empty array is safe.
I have a small patch for this and can open a PR.
Possibly related
#258 reports release builds failing with "is not a Worklet" when the Reanimated plugin and the worklets-core plugin are used together. It might be the same root cause, but I haven't verified that.
- Ngôn ngữ chính
- C++
- Star
- 791
- Fork
- 66
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của margelo/react-native-worklets-core
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
margelo/react-native-worklets-core#271 · 1 bình luận ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
margelo/react-native-worklets-core#269 · 2 reaction ·
-
Unable to download JS bundleĐang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 35/100
margelo/react-native-worklets-core#268 · 2 bình luận ·
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 72/100
margelo/react-native-worklets-core#267 · 1 bình luận · 1 reaction ·
Tất cả issue của margelo/react-native-worklets-core
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
KhronosGroup/Vulkan-Tutorial#534 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
Maintainer thường phản hồi trong vòng 2 ngày
-
bug IO
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
MrNeRF/LichtFeld-Studio#3824 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
throneproj/Throne#2043 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
Perchik71/Creation-Kit-Platform-Extended#267 ·
Maintainer thường phản hồi trong vòng 1 ngày