mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
fix(transformer/react): support emit_full_signatures option in refresh plugin (#5629)
This commit is contained in:
parent
b8f8dd6612
commit
3bf6aaf06a
10 changed files with 99 additions and 14 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
|
@ -1957,6 +1957,7 @@ dependencies = [
|
|||
name = "oxc_transformer"
|
||||
version = "0.27.0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"dashmap 6.0.1",
|
||||
"indexmap",
|
||||
"oxc-browserslist",
|
||||
|
|
@ -1975,6 +1976,7 @@ dependencies = [
|
|||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2701,6 +2703,17 @@ dependencies = [
|
|||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ oxc_span = { workspace = true }
|
|||
oxc_syntax = { workspace = true, features = ["to_js_string"] }
|
||||
oxc_traverse = { workspace = true }
|
||||
|
||||
base64 = { workspace = true }
|
||||
dashmap = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
oxc-browserslist = { workspace = true }
|
||||
|
|
@ -37,6 +38,7 @@ ropey = { workspace = true }
|
|||
rustc-hash = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sha1 = { version = "0.10.6" }
|
||||
|
||||
[dev-dependencies]
|
||||
oxc_codegen = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -195,15 +195,28 @@ impl ReactOptions {
|
|||
#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct ReactRefreshOptions {
|
||||
/// Specify the identifier of the refresh registration variable.
|
||||
///
|
||||
/// Defaults to `$RefreshReg$`.
|
||||
#[serde(default = "default_refresh_reg")]
|
||||
pub refresh_reg: String,
|
||||
|
||||
/// Specify the identifier of the refresh signature variable.
|
||||
///
|
||||
/// Defaults to `$RefreshSig$`.
|
||||
#[serde(default = "default_refresh_sig")]
|
||||
pub refresh_sig: String,
|
||||
|
||||
/// Controls whether to emit full signatures or use a more compact representation.
|
||||
///
|
||||
/// When set to `true`, this option causes this plugin to emit full, readable signatures
|
||||
/// for React components and hooks. This can be useful for debugging and development purposes.
|
||||
///
|
||||
/// When set to `false` (default), the transformer will use a more compact representation.
|
||||
/// Specifically, it generates a SHA-1 hash of the signature and then encodes it using Base64.
|
||||
/// This process produces a deterministic, compact representation that's suitable for
|
||||
/// production builds while still uniquely identifying components.
|
||||
///
|
||||
/// Defaults to `false`.
|
||||
#[serde(default)]
|
||||
pub emit_full_signatures: bool,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::{cell::Cell, iter::once};
|
||||
|
||||
use base64::prelude::{Engine, BASE64_STANDARD};
|
||||
use oxc_allocator::CloneIn;
|
||||
use oxc_ast::{ast::*, match_expression, match_member_expression};
|
||||
use oxc_semantic::{Reference, ReferenceFlags, ScopeId, SymbolFlags, SymbolId};
|
||||
|
|
@ -7,6 +8,7 @@ use oxc_span::{Atom, GetSpan, SPAN};
|
|||
use oxc_syntax::operator::AssignmentOperator;
|
||||
use oxc_traverse::{Ancestor, Traverse, TraverseCtx};
|
||||
use rustc_hash::FxHashMap;
|
||||
use sha1::{Digest, Sha1};
|
||||
|
||||
use super::options::ReactRefreshOptions;
|
||||
use crate::context::Ctx;
|
||||
|
|
@ -22,7 +24,7 @@ use crate::context::Ctx;
|
|||
pub struct ReactRefresh<'a> {
|
||||
refresh_reg: Atom<'a>,
|
||||
refresh_sig: Atom<'a>,
|
||||
_emit_full_signatures: bool,
|
||||
emit_full_signatures: bool,
|
||||
registrations: Vec<(SymbolId, Atom<'a>)>,
|
||||
ctx: Ctx<'a>,
|
||||
signature_declarator_items: Vec<oxc_allocator::Vec<'a, VariableDeclarator<'a>>>,
|
||||
|
|
@ -41,7 +43,7 @@ impl<'a> ReactRefresh<'a> {
|
|||
Self {
|
||||
refresh_reg: ctx.ast.atom(&options.refresh_reg),
|
||||
refresh_sig: ctx.ast.atom(&options.refresh_sig),
|
||||
_emit_full_signatures: options.emit_full_signatures,
|
||||
emit_full_signatures: options.emit_full_signatures,
|
||||
signature_declarator_items: Vec::new(),
|
||||
registrations: Vec::default(),
|
||||
ctx,
|
||||
|
|
@ -542,12 +544,23 @@ impl<'a> ReactRefresh<'a> {
|
|||
) -> Option<(BindingIdentifier<'a>, oxc_allocator::Vec<'a, Argument<'a>>)> {
|
||||
let fn_hook_calls = self.hook_calls.remove(&scope_id)?;
|
||||
|
||||
let key = fn_hook_calls
|
||||
let mut key = fn_hook_calls
|
||||
.into_iter()
|
||||
.map(|(hook_name, hook_key)| format!("{hook_name}{{{hook_key}}}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\\n");
|
||||
|
||||
if !self.emit_full_signatures {
|
||||
// Prefer to hash when we can (e.g. outside of ASTExplorer).
|
||||
// This makes it deterministically compact, even if there's
|
||||
// e.g. a useState initializer with some code inside.
|
||||
// We also need it for www that has transforms like cx()
|
||||
// that don't understand if something is part of a string.
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(key);
|
||||
key = BASE64_STANDARD.encode(hasher.finalize());
|
||||
}
|
||||
|
||||
let callee_list = self.non_builtin_hooks_callee.remove(&scope_id).unwrap_or_default();
|
||||
let callee_len = callee_list.len();
|
||||
let custom_hooks_in_scope = ctx.ast.vec_from_iter(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
commit: 3bcfee23
|
||||
|
||||
Passed: 17/50
|
||||
Passed: 17/51
|
||||
|
||||
# All Passed:
|
||||
* babel-plugin-transform-nullish-coalescing-operator
|
||||
|
|
@ -167,7 +167,7 @@ rebuilt : SymbolId(2): []
|
|||
x Output mismatch
|
||||
|
||||
|
||||
# babel-plugin-transform-react-jsx (3/28)
|
||||
# babel-plugin-transform-react-jsx (3/29)
|
||||
* refresh/can-handle-implicit-arrow-returns/input.jsx
|
||||
Symbol reference IDs mismatch:
|
||||
after transform: SymbolId(9): [ReferenceId(23), ReferenceId(24), ReferenceId(25)]
|
||||
|
|
@ -268,6 +268,9 @@ rebuilt : ["$RefreshSig$", "item", "useFoo"]
|
|||
* refresh/does-not-transform-it-because-it-is-not-used-in-the-AST/input.jsx
|
||||
x Output mismatch
|
||||
|
||||
* refresh/emit-full-signatures-option/input.jsx
|
||||
x Output mismatch
|
||||
|
||||
* refresh/generates-signatures-for-function-declarations-calling-hooks/input.jsx
|
||||
x Output mismatch
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
export default function Bar () {
|
||||
useContext(X)
|
||||
return <Foo />
|
||||
};
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"plugins": [
|
||||
[
|
||||
"transform-react-jsx",
|
||||
{
|
||||
"refresh": {
|
||||
"emitFullSignatures": false
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
var _s = $RefreshSig$();
|
||||
export default function Bar() {
|
||||
_s();
|
||||
useContext(X);
|
||||
return _jsx(Foo, {});
|
||||
}
|
||||
_s(Bar, "gDsCjeeItUuvgOWf1v4qoK9RF6k=");
|
||||
_c = Bar;
|
||||
;
|
||||
var _c;
|
||||
$RefreshReg$(_c, "Bar");
|
||||
|
|
@ -1,5 +1,12 @@
|
|||
{
|
||||
"plugins": [["transform-react-jsx", {
|
||||
"refresh": {}
|
||||
}]]
|
||||
"plugins": [
|
||||
[
|
||||
"transform-react-jsx",
|
||||
{
|
||||
"refresh": {
|
||||
"emitFullSignatures": true
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
{
|
||||
"plugins": [["transform-react-jsx", {
|
||||
"refresh": {
|
||||
"refreshReg": "import.meta.refreshReg",
|
||||
"refreshSig": "import.meta.refreshSig"
|
||||
}
|
||||
}]]
|
||||
"plugins": [
|
||||
[
|
||||
"transform-react-jsx",
|
||||
{
|
||||
"refresh": {
|
||||
"refreshReg": "import.meta.refreshReg",
|
||||
"refreshSig": "import.meta.refreshSig",
|
||||
"emitFullSignatures": true
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue