mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
refactor(ast, isolated_declarations, transformer): mark AstBuilder::copy as an unsafe function (#4907)
`AstBuilder::copy` is completely unsound (#3483), and we need to remove it. Make it an `unsafe` function to discourage any further usage of it in meantime.
This commit is contained in:
parent
46fb3cbb3e
commit
1eb59d2b5e
18 changed files with 267 additions and 115 deletions
|
|
@ -62,10 +62,10 @@ impl<'a> AstBuilder<'a> {
|
|||
/// This method is completely unsound and should not be used.
|
||||
/// We need to remove all uses of it. Please don't add any more!
|
||||
/// <https://github.com/oxc-project/oxc/issues/3483>
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
#[inline]
|
||||
pub fn copy<T>(self, src: &T) -> T {
|
||||
pub unsafe fn copy<T>(self, src: &T) -> T {
|
||||
// SAFETY: Not safe (see above)
|
||||
|
||||
unsafe { std::mem::transmute_copy(src) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
|
||||
if property.accessibility.map_or(true, |a| !a.is_private()) {
|
||||
if property.type_annotation.is_some() {
|
||||
type_annotations = self.ast.copy(&property.type_annotation);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
type_annotations = unsafe { self.ast.copy(&property.type_annotation) };
|
||||
} else if let Some(expr) = property.value.as_ref() {
|
||||
let ts_type = if property.readonly {
|
||||
// `field = 'string'` remain `field = 'string'` instead of `field: 'string'`
|
||||
|
|
@ -71,7 +72,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
.transform_template_to_string(lit)
|
||||
.map(Expression::StringLiteral);
|
||||
} else {
|
||||
value = Some(self.ast.copy(expr));
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
value = Some(unsafe { self.ast.copy(expr) });
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
@ -91,7 +93,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
property.r#type,
|
||||
property.span,
|
||||
self.ast.vec(),
|
||||
self.ast.copy(&property.key),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&property.key) },
|
||||
value,
|
||||
property.computed,
|
||||
property.r#static,
|
||||
|
|
@ -116,12 +119,15 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let value = self.ast.alloc_function(
|
||||
FunctionType::TSEmptyBodyFunctionExpression,
|
||||
function.span,
|
||||
self.ast.copy(&function.id),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&function.id) },
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
self.ast.copy(&function.type_parameters),
|
||||
self.ast.copy(&function.this_param),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&function.type_parameters) },
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&function.this_param) },
|
||||
params,
|
||||
return_type,
|
||||
Option::<FunctionBody>::None,
|
||||
|
|
@ -131,7 +137,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
definition.r#type,
|
||||
definition.span,
|
||||
self.ast.vec(),
|
||||
self.ast.copy(&definition.key),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&definition.key) },
|
||||
value,
|
||||
definition.kind,
|
||||
definition.computed,
|
||||
|
|
@ -209,7 +216,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
};
|
||||
self.create_class_property(
|
||||
r#type,
|
||||
self.ast.copy(&method.key),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&method.key) },
|
||||
method.r#static,
|
||||
method.r#override,
|
||||
self.transform_accessibility(method.accessibility),
|
||||
|
|
@ -247,7 +255,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
None
|
||||
} else {
|
||||
// transformed params will definitely have type annotation
|
||||
self.ast.copy(¶ms.items[index].pattern.type_annotation)
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(¶ms.items[index].pattern.type_annotation) }
|
||||
};
|
||||
if let Some(new_element) =
|
||||
self.transform_formal_parameter_to_class_property(param, type_annotation)
|
||||
|
|
@ -289,7 +298,10 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
MethodDefinitionKind::Get => {
|
||||
let return_type = self.infer_function_return_type(function);
|
||||
if let Some(return_type) = return_type {
|
||||
inferred_accessor_types.insert(name, self.ast.copy(&return_type));
|
||||
inferred_accessor_types.insert(name, {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&return_type) }
|
||||
});
|
||||
}
|
||||
}
|
||||
MethodDefinitionKind::Set => {
|
||||
|
|
@ -300,7 +312,10 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
self.infer_type_from_formal_parameter(param)
|
||||
.map(|x| self.ast.alloc_ts_type_annotation(SPAN, x))
|
||||
},
|
||||
|t| Some(self.ast.copy(t)),
|
||||
|t| {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { Some(self.ast.copy(t)) }
|
||||
},
|
||||
);
|
||||
if let Some(type_annotation) = type_annotation {
|
||||
inferred_accessor_types.insert(name, type_annotation);
|
||||
|
|
@ -373,9 +388,10 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
|n| {
|
||||
self.transform_set_accessor_params(
|
||||
&function.params,
|
||||
inferred_accessor_types
|
||||
.get(&self.ast.atom(&n))
|
||||
.map(|t| self.ast.copy(t)),
|
||||
inferred_accessor_types.get(&self.ast.atom(&n)).map(|t| {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(t) }
|
||||
}),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -403,9 +419,10 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
}
|
||||
MethodDefinitionKind::Get => {
|
||||
let rt = method.key.static_name().and_then(|name| {
|
||||
inferred_accessor_types
|
||||
.get(&self.ast.atom(&name))
|
||||
.map(|t| self.ast.copy(t))
|
||||
inferred_accessor_types.get(&self.ast.atom(&name)).map(|t| {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(t) }
|
||||
})
|
||||
});
|
||||
if rt.is_none() {
|
||||
self.error(accessor_must_have_explicit_return_type(
|
||||
|
|
@ -446,14 +463,18 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
property.r#type,
|
||||
property.span,
|
||||
self.ast.vec(),
|
||||
self.ast.copy(&property.key),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&property.key) },
|
||||
None,
|
||||
property.computed,
|
||||
property.r#static,
|
||||
);
|
||||
elements.push(new_element);
|
||||
}
|
||||
ClassElement::TSIndexSignature(_) => elements.push(self.ast.copy(element)),
|
||||
ClassElement::TSIndexSignature(_) => elements.push({
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(element) }
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -490,11 +511,16 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
decl.r#type,
|
||||
decl.span,
|
||||
self.ast.vec(),
|
||||
self.ast.copy(&decl.id),
|
||||
self.ast.copy(&decl.type_parameters),
|
||||
self.ast.copy(&decl.super_class),
|
||||
self.ast.copy(&decl.super_type_parameters),
|
||||
self.ast.copy(&decl.implements),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.id) },
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.type_parameters) },
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.super_class) },
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.super_type_parameters) },
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.implements) },
|
||||
body,
|
||||
decl.r#abstract,
|
||||
declare.unwrap_or_else(|| self.is_declare()),
|
||||
|
|
@ -510,7 +536,10 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
if items.first().map_or(true, |item| item.pattern.type_annotation.is_none()) {
|
||||
let kind = items.first().map_or_else(
|
||||
|| self.ast.binding_pattern_kind_binding_identifier(SPAN, "value"),
|
||||
|item| self.ast.copy(&item.pattern.kind),
|
||||
|item| {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&item.pattern.kind) }
|
||||
},
|
||||
);
|
||||
|
||||
self.create_formal_parameters(kind, type_annotation)
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
init =
|
||||
self.transform_template_to_string(lit).map(Expression::StringLiteral);
|
||||
} else {
|
||||
init = Some(self.ast.copy(init_expr));
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
init = Some(unsafe { self.ast.copy(init_expr) });
|
||||
}
|
||||
} else if !decl.kind.is_const()
|
||||
|| !matches!(init_expr, Expression::TemplateLiteral(_))
|
||||
|
|
@ -94,10 +95,14 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
}
|
||||
}
|
||||
let id = binding_type.map_or_else(
|
||||
|| self.ast.copy(&decl.id),
|
||||
|| {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.id) }
|
||||
},
|
||||
|ts_type| {
|
||||
self.ast.binding_pattern(
|
||||
self.ast.copy(&decl.id.kind),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.id.kind) },
|
||||
Some(self.ast.ts_type_annotation(SPAN, ts_type)),
|
||||
decl.id.optional,
|
||||
)
|
||||
|
|
@ -149,11 +154,13 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
decl: &Box<'a, TSModuleDeclaration<'a>>,
|
||||
) -> Box<'a, TSModuleDeclaration<'a>> {
|
||||
if decl.declare {
|
||||
return self.ast.copy(decl);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
return unsafe { self.ast.copy(decl) };
|
||||
}
|
||||
|
||||
let Some(body) = &decl.body else {
|
||||
return self.ast.copy(decl);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
return unsafe { self.ast.copy(decl) };
|
||||
};
|
||||
|
||||
match body {
|
||||
|
|
@ -161,7 +168,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let inner = self.transform_ts_module_declaration(decl);
|
||||
self.ast.alloc_ts_module_declaration(
|
||||
decl.span,
|
||||
self.ast.copy(&decl.id),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.id) },
|
||||
Some(TSModuleDeclarationBody::TSModuleDeclaration(inner)),
|
||||
decl.kind,
|
||||
self.is_declare(),
|
||||
|
|
@ -171,7 +179,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let body = self.transform_ts_module_block(block);
|
||||
self.ast.alloc_ts_module_declaration(
|
||||
decl.span,
|
||||
self.ast.copy(&decl.id),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.id) },
|
||||
Some(TSModuleDeclarationBody::TSModuleBlock(body)),
|
||||
decl.kind,
|
||||
self.is_declare(),
|
||||
|
|
@ -213,7 +222,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
Declaration::TSTypeAliasDeclaration(alias_decl) => {
|
||||
self.visit_ts_type_alias_declaration(alias_decl);
|
||||
if !check_binding || self.scope.has_reference(&alias_decl.id.name) {
|
||||
Some(self.ast.copy(decl))
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
Some(unsafe { self.ast.copy(decl) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -221,7 +231,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
Declaration::TSInterfaceDeclaration(interface_decl) => {
|
||||
self.visit_ts_interface_declaration(interface_decl);
|
||||
if !check_binding || self.scope.has_reference(&interface_decl.id.name) {
|
||||
Some(self.ast.copy(decl))
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
Some(unsafe { self.ast.copy(decl) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -250,7 +261,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
}
|
||||
Declaration::TSImportEqualsDeclaration(decl) => {
|
||||
if !check_binding || self.scope.has_reference(&decl.id.name) {
|
||||
Some(Declaration::TSImportEqualsDeclaration(self.ast.copy(decl)))
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
Some(Declaration::TSImportEqualsDeclaration(unsafe { self.ast.copy(decl) }))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
|
||||
let member = self.ast.ts_enum_member(
|
||||
member.span,
|
||||
self.ast.copy(&member.id),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&member.id) },
|
||||
value.map(|v| match v {
|
||||
ConstantValue::Number(v) => {
|
||||
let is_negative = v < 0.0;
|
||||
|
|
@ -94,7 +95,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
|
||||
Some(self.ast.declaration_ts_enum(
|
||||
decl.span,
|
||||
self.ast.copy(&decl.id),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.id) },
|
||||
members,
|
||||
decl.r#const,
|
||||
self.is_declare(),
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ pub struct FormalParameterBindingPattern<'a> {
|
|||
impl<'a> VisitMut<'a> for FormalParameterBindingPattern<'a> {
|
||||
fn visit_binding_pattern_kind(&mut self, kind: &mut BindingPatternKind<'a>) {
|
||||
if let BindingPatternKind::AssignmentPattern(assignment) = kind {
|
||||
*kind = self.ast.copy(&assignment.left.kind);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
*kind = unsafe { self.ast.copy(&assignment.left.kind) };
|
||||
}
|
||||
|
||||
walk_binding_pattern_kind(self, kind);
|
||||
|
|
|
|||
|
|
@ -30,12 +30,15 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
Some(self.ast.alloc_function(
|
||||
func.r#type,
|
||||
func.span,
|
||||
self.ast.copy(&func.id),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&func.id) },
|
||||
false,
|
||||
false,
|
||||
declare.unwrap_or_else(|| self.is_declare()),
|
||||
self.ast.copy(&func.type_parameters),
|
||||
self.ast.copy(&func.this_param),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&func.type_parameters) },
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&func.this_param) },
|
||||
params,
|
||||
return_type,
|
||||
Option::<FunctionBody>::None,
|
||||
|
|
@ -61,9 +64,11 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let is_assignment_pattern = pattern.kind.is_assignment_pattern();
|
||||
let mut pattern =
|
||||
if let BindingPatternKind::AssignmentPattern(pattern) = ¶m.pattern.kind {
|
||||
self.ast.copy(&pattern.left)
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&pattern.left) }
|
||||
} else {
|
||||
self.ast.copy(¶m.pattern)
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(¶m.pattern) }
|
||||
};
|
||||
|
||||
FormalParameterBindingPattern::remove_assignments_from_kind(self.ast, &mut pattern.kind);
|
||||
|
|
@ -72,7 +77,10 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let type_annotation = pattern
|
||||
.type_annotation
|
||||
.as_ref()
|
||||
.map(|type_annotation| self.ast.copy(&type_annotation.type_annotation))
|
||||
.map(|type_annotation| {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&type_annotation.type_annotation) }
|
||||
})
|
||||
.or_else(|| {
|
||||
// report error for has no type annotation
|
||||
let new_type = self.infer_type_from_formal_parameter(param);
|
||||
|
|
@ -106,7 +114,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
});
|
||||
|
||||
pattern = self.ast.binding_pattern(
|
||||
self.ast.copy(&pattern.kind),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&pattern.kind) },
|
||||
type_annotation,
|
||||
// if it's assignment pattern, it's optional
|
||||
pattern.optional || (!is_remaining_params_have_required && is_assignment_pattern),
|
||||
|
|
@ -121,7 +130,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
params: &FormalParameters<'a>,
|
||||
) -> Box<'a, FormalParameters<'a>> {
|
||||
if params.kind.is_signature() || (params.rest.is_none() && params.items.is_empty()) {
|
||||
return self.ast.alloc(self.ast.copy(params));
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
return self.ast.alloc(unsafe { self.ast.copy(params) });
|
||||
}
|
||||
|
||||
let items =
|
||||
|
|
@ -143,7 +153,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
params.span,
|
||||
FormalParameterKind::Signature,
|
||||
items,
|
||||
self.ast.copy(¶ms.rest),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(¶ms.rest) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,10 +32,16 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
_ => None,
|
||||
},
|
||||
Expression::FunctionExpression(func) => {
|
||||
self.transform_function_to_ts_type(func).map(|x| self.ast.copy(&x))
|
||||
self.transform_function_to_ts_type(func).map(|x| {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&x) }
|
||||
})
|
||||
}
|
||||
Expression::ArrowFunctionExpression(func) => {
|
||||
self.transform_arrow_function_to_ts_type(func).map(|x| self.ast.copy(&x))
|
||||
self.transform_arrow_function_to_ts_type(func).map(|x| {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&x) }
|
||||
})
|
||||
}
|
||||
Expression::ObjectExpression(expr) => {
|
||||
Some(self.transform_object_expression_to_ts_type(expr, false))
|
||||
|
|
@ -48,7 +54,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
if expr.type_annotation.is_const_type_reference() {
|
||||
self.transform_expression_to_ts_type(&expr.expression)
|
||||
} else {
|
||||
Some(self.ast.copy(&expr.type_annotation))
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
Some(unsafe { self.ast.copy(&expr.type_annotation) })
|
||||
}
|
||||
}
|
||||
Expression::ClassExpression(expr) => {
|
||||
|
|
@ -64,7 +71,10 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
Expression::TSSatisfiesExpression(expr) => {
|
||||
self.infer_type_from_expression(&expr.expression)
|
||||
}
|
||||
Expression::TSTypeAssertion(expr) => Some(self.ast.copy(&expr.type_annotation)),
|
||||
Expression::TSTypeAssertion(expr) => {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
Some(unsafe { self.ast.copy(&expr.type_annotation) })
|
||||
}
|
||||
Expression::UnaryExpression(expr) => {
|
||||
if Self::can_infer_unary_expression(expr) {
|
||||
self.infer_type_from_expression(&expr.argument)
|
||||
|
|
@ -81,11 +91,15 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
param: &FormalParameter<'a>,
|
||||
) -> Option<TSType<'a>> {
|
||||
if param.pattern.type_annotation.is_some() {
|
||||
param.pattern.type_annotation.as_ref().map(|x| self.ast.copy(&x.type_annotation));
|
||||
param.pattern.type_annotation.as_ref().map(|x| {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&x.type_annotation) }
|
||||
});
|
||||
}
|
||||
if let BindingPatternKind::AssignmentPattern(pattern) = ¶m.pattern.kind {
|
||||
if let Some(annotation) = pattern.left.type_annotation.as_ref() {
|
||||
Some(self.ast.copy(&annotation.type_annotation))
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
Some(unsafe { self.ast.copy(&annotation.type_annotation) })
|
||||
} else {
|
||||
if let Expression::TSAsExpression(expr) = &pattern.right {
|
||||
if !expr.type_annotation.is_keyword_or_literal() {
|
||||
|
|
@ -105,7 +119,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
function: &Function<'a>,
|
||||
) -> Option<Box<'a, TSTypeAnnotation<'a>>> {
|
||||
if function.return_type.is_some() {
|
||||
return self.ast.copy(&function.return_type);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
return unsafe { self.ast.copy(&function.return_type) };
|
||||
}
|
||||
|
||||
if function.r#async || function.generator {
|
||||
|
|
@ -123,7 +138,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
function: &ArrowFunctionExpression<'a>,
|
||||
) -> Option<Box<'a, TSTypeAnnotation<'a>>> {
|
||||
if function.return_type.is_some() {
|
||||
return self.ast.copy(&function.return_type);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
return unsafe { self.ast.copy(&function.return_type) };
|
||||
}
|
||||
|
||||
if function.r#async {
|
||||
|
|
|
|||
|
|
@ -99,12 +99,15 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
stmts: &oxc_allocator::Vec<'a, Statement<'a>>,
|
||||
) -> oxc_allocator::Vec<'a, Statement<'a>> {
|
||||
let mut new_ast_stmts = self.ast.vec::<Statement<'a>>();
|
||||
for stmt in Self::remove_function_overloads_implementation(self.ast.copy(stmts)) {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
for stmt in Self::remove_function_overloads_implementation(unsafe { self.ast.copy(stmts) })
|
||||
{
|
||||
if let Some(decl) = stmt.as_declaration() {
|
||||
if let Some(decl) = self.transform_declaration(decl, false) {
|
||||
new_ast_stmts.push(Statement::from(decl));
|
||||
} else {
|
||||
new_ast_stmts.push(Statement::from(self.ast.copy(decl)));
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
new_ast_stmts.push(Statement::from(unsafe { self.ast.copy(decl) }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -127,19 +130,27 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
// 2. Transform export declarations
|
||||
// 3. Collect all bindings / reference from module declarations
|
||||
// 4. Collect transformed indexes
|
||||
for stmt in Self::remove_function_overloads_implementation(self.ast.copy(stmts)) {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
for stmt in Self::remove_function_overloads_implementation(unsafe { self.ast.copy(stmts) })
|
||||
{
|
||||
match stmt {
|
||||
match_declaration!(Statement) => {
|
||||
match stmt.to_declaration() {
|
||||
Declaration::VariableDeclaration(decl) => {
|
||||
variables_declarations.push_back(
|
||||
self.ast.copy(&decl.declarations).into_iter().collect::<Vec<_>>(),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.declarations) }
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
variable_transformed_indexes.push_back(FxHashSet::default());
|
||||
}
|
||||
Declaration::UsingDeclaration(decl) => {
|
||||
variables_declarations.push_back(
|
||||
self.ast.copy(&decl.declarations).into_iter().collect::<Vec<_>>(),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.declarations) }
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
variable_transformed_indexes.push_back(FxHashSet::default());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
.transform_class(decl, Some(false))
|
||||
.map(|d| (None, ExportDefaultDeclarationKind::ClassDeclaration(d))),
|
||||
ExportDefaultDeclarationKind::TSInterfaceDeclaration(_) => {
|
||||
Some((None, self.ast.copy(&decl.declaration)))
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
Some((None, unsafe { self.ast.copy(&decl.declaration) }))
|
||||
}
|
||||
expr @ match_expression!(ExportDefaultDeclarationKind) => {
|
||||
let expr = expr.to_expression();
|
||||
|
|
@ -95,7 +96,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
) -> Option<Box<'a, ImportDeclaration<'a>>> {
|
||||
let specifiers = decl.specifiers.as_ref()?;
|
||||
|
||||
let mut specifiers = self.ast.copy(specifiers);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
let mut specifiers = unsafe { self.ast.copy(specifiers) };
|
||||
specifiers.retain(|specifier| match specifier {
|
||||
ImportDeclarationSpecifier::ImportSpecifier(specifier) => {
|
||||
self.scope.has_reference(&specifier.local.name)
|
||||
|
|
@ -114,8 +116,10 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
Some(self.ast.alloc_import_declaration(
|
||||
decl.span,
|
||||
Some(specifiers),
|
||||
self.ast.copy(&decl.source),
|
||||
self.ast.copy(&decl.with_clause),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.source) },
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&decl.with_clause) },
|
||||
decl.import_kind,
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ impl<'a> Visit<'a> for FunctionReturnType<'a> {
|
|||
return;
|
||||
}
|
||||
}
|
||||
self.return_expression = Some(self.ast.copy(&stmt.argument));
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
self.return_expression = Some(unsafe { self.ast.copy(&stmt.argument) });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,10 +26,12 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
return_type.map(|return_type| {
|
||||
self.ast.ts_type_function_type(
|
||||
func.span,
|
||||
self.ast.copy(&func.this_param),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&func.this_param) },
|
||||
params,
|
||||
return_type,
|
||||
self.ast.copy(&func.type_parameters),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&func.type_parameters) },
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
@ -55,7 +57,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
None,
|
||||
params,
|
||||
return_type,
|
||||
self.ast.copy(&func.type_parameters),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&func.type_parameters) },
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
@ -95,14 +98,17 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let params = self.transform_formal_parameters(&function.params);
|
||||
return Some(self.ast.ts_signature_method_signature(
|
||||
object.span,
|
||||
self.ast.copy(&object.key),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&object.key) },
|
||||
object.computed,
|
||||
false,
|
||||
TSMethodSignatureKind::Method,
|
||||
self.ast.copy(&function.this_param),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&function.this_param) },
|
||||
params,
|
||||
return_type,
|
||||
self.ast.copy(&function.type_parameters),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&function.type_parameters) },
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -123,7 +129,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
false,
|
||||
false,
|
||||
is_const,
|
||||
self.ast.copy(&object.key),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(&object.key) },
|
||||
type_annotation.map(|type_annotation| {
|
||||
self.ast.ts_type_annotation(SPAN, type_annotation)
|
||||
}),
|
||||
|
|
@ -169,18 +176,34 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions
|
||||
pub fn transform_expression_to_ts_type(&self, expr: &Expression<'a>) -> Option<TSType<'a>> {
|
||||
match expr {
|
||||
Expression::BooleanLiteral(lit) => Some(
|
||||
self.ast.ts_type_literal_type(SPAN, TSLiteral::BooleanLiteral(self.ast.copy(lit))),
|
||||
),
|
||||
Expression::NumericLiteral(lit) => Some(
|
||||
self.ast.ts_type_literal_type(SPAN, TSLiteral::NumericLiteral(self.ast.copy(lit))),
|
||||
),
|
||||
Expression::BigIntLiteral(lit) => Some(
|
||||
self.ast.ts_type_literal_type(SPAN, TSLiteral::BigIntLiteral(self.ast.copy(lit))),
|
||||
),
|
||||
Expression::StringLiteral(lit) => Some(
|
||||
self.ast.ts_type_literal_type(SPAN, TSLiteral::StringLiteral(self.ast.copy(lit))),
|
||||
),
|
||||
Expression::BooleanLiteral(lit) => Some(self.ast.ts_type_literal_type(
|
||||
SPAN,
|
||||
TSLiteral::BooleanLiteral({
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(lit) }
|
||||
}),
|
||||
)),
|
||||
Expression::NumericLiteral(lit) => Some(self.ast.ts_type_literal_type(
|
||||
SPAN,
|
||||
TSLiteral::NumericLiteral({
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(lit) }
|
||||
}),
|
||||
)),
|
||||
Expression::BigIntLiteral(lit) => Some(self.ast.ts_type_literal_type(
|
||||
SPAN,
|
||||
TSLiteral::BigIntLiteral({
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(lit) }
|
||||
}),
|
||||
)),
|
||||
Expression::StringLiteral(lit) => Some(self.ast.ts_type_literal_type(
|
||||
SPAN,
|
||||
TSLiteral::StringLiteral({
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast.copy(lit) }
|
||||
}),
|
||||
)),
|
||||
Expression::NullLiteral(lit) => Some(self.ast.ts_type_null_keyword(lit.span)),
|
||||
Expression::Identifier(ident) => match ident.name.as_str() {
|
||||
"undefined" => Some(self.ast.ts_type_undefined_keyword(ident.span)),
|
||||
|
|
@ -195,7 +218,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
if Self::can_infer_unary_expression(expr) {
|
||||
Some(self.ast.ts_type_literal_type(
|
||||
SPAN,
|
||||
TSLiteral::UnaryExpression(self.ast.copy(expr)),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
TSLiteral::UnaryExpression(unsafe { self.ast.copy(expr) }),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
|
@ -215,7 +239,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
if expr.type_annotation.is_const_type_reference() {
|
||||
self.transform_expression_to_ts_type(&expr.expression)
|
||||
} else {
|
||||
Some(self.ast.copy(&expr.type_annotation))
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
Some(unsafe { self.ast.copy(&expr.type_annotation) })
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
|
|
|
|||
|
|
@ -184,15 +184,17 @@ impl<'a> ArrowFunctions<'a> {
|
|||
arrow_function_expr: &mut ArrowFunctionExpression<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) -> Expression<'a> {
|
||||
let mut body = self.ctx.ast.copy(&arrow_function_expr.body);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
let mut body = unsafe { self.ctx.ast.copy(&arrow_function_expr.body) };
|
||||
|
||||
if arrow_function_expr.expression {
|
||||
let first_stmt = body.statements.remove(0);
|
||||
if let Statement::ExpressionStatement(stmt) = first_stmt {
|
||||
let return_statement = self
|
||||
.ctx
|
||||
.ast
|
||||
.statement_return(stmt.span, Some(self.ctx.ast.copy(&stmt.expression)));
|
||||
let return_statement = self.ctx.ast.statement_return(
|
||||
stmt.span,
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
Some(unsafe { self.ctx.ast.copy(&stmt.expression) }),
|
||||
);
|
||||
body.statements.push(return_statement);
|
||||
}
|
||||
}
|
||||
|
|
@ -222,10 +224,13 @@ impl<'a> ArrowFunctions<'a> {
|
|||
r#async: arrow_function_expr.r#async,
|
||||
declare: false,
|
||||
this_param: None,
|
||||
params: self.ctx.ast.copy(&arrow_function_expr.params),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
params: unsafe { self.ctx.ast.copy(&arrow_function_expr.params) },
|
||||
body: Some(body),
|
||||
type_parameters: self.ctx.ast.copy(&arrow_function_expr.type_parameters),
|
||||
return_type: self.ctx.ast.copy(&arrow_function_expr.return_type),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
type_parameters: unsafe { self.ctx.ast.copy(&arrow_function_expr.type_parameters) },
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
return_type: unsafe { self.ctx.ast.copy(&arrow_function_expr.return_type) },
|
||||
scope_id: Cell::new(scope_id),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,13 @@ impl<'a> NullishCoalescingOperator<'a> {
|
|||
let op = BinaryOperator::StrictInequality;
|
||||
let null = ctx.ast.expression_null_literal(SPAN);
|
||||
let left = ctx.ast.expression_binary(SPAN, assignment, op, null);
|
||||
let right = ctx.ast.expression_binary(SPAN, ctx.ast.copy(&reference), op, ctx.ast.void_0());
|
||||
let right = ctx.ast.expression_binary(
|
||||
SPAN,
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { ctx.ast.copy(&reference) },
|
||||
op,
|
||||
ctx.ast.void_0(),
|
||||
);
|
||||
let test = ctx.ast.expression_logical(SPAN, left, LogicalOperator::And, right);
|
||||
|
||||
*expr = ctx.ast.expression_conditional(SPAN, test, reference, logical_expr.right);
|
||||
|
|
|
|||
|
|
@ -523,7 +523,10 @@ impl<'a> ReactJsx<'a> {
|
|||
// deopt if spreading an object with `__proto__` key
|
||||
if !matches!(&spread.argument, Expression::ObjectExpression(o) if o.has_proto())
|
||||
{
|
||||
arguments.push(Argument::from(self.ast().copy(&spread.argument)));
|
||||
arguments.push(Argument::from({
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast().copy(&spread.argument) }
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -813,10 +816,12 @@ impl<'a> ReactJsx<'a> {
|
|||
}
|
||||
JSXAttributeItem::SpreadAttribute(attr) => match &attr.argument {
|
||||
Expression::ObjectExpression(expr) if !expr.has_proto() => {
|
||||
properties.extend(self.ast().copy(&expr.properties));
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
properties.extend(unsafe { self.ast().copy(&expr.properties) });
|
||||
}
|
||||
expr => {
|
||||
let argument = self.ast().copy(expr);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
let argument = unsafe { self.ast().copy(expr) };
|
||||
let object_property =
|
||||
self.ast().object_property_kind_spread_element(attr.span, argument);
|
||||
properties.push(object_property);
|
||||
|
|
@ -842,7 +847,10 @@ impl<'a> ReactJsx<'a> {
|
|||
self.transform_jsx(&JSXElementOrFragment::Fragment(e), ctx)
|
||||
}
|
||||
Some(JSXAttributeValue::ExpressionContainer(c)) => match &c.expression {
|
||||
e @ match_expression!(JSXExpression) => self.ast().copy(e.to_expression()),
|
||||
e @ match_expression!(JSXExpression) => {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ast().copy(e.to_expression()) }
|
||||
}
|
||||
JSXExpression::EmptyExpression(e) => {
|
||||
self.ast().expression_boolean_literal(e.span, true)
|
||||
}
|
||||
|
|
@ -859,7 +867,10 @@ impl<'a> ReactJsx<'a> {
|
|||
match child {
|
||||
JSXChild::Text(text) => self.transform_jsx_text(text),
|
||||
JSXChild::ExpressionContainer(e) => match &e.expression {
|
||||
e @ match_expression!(JSXExpression) => Some(self.ast().copy(e.to_expression())),
|
||||
e @ match_expression!(JSXExpression) => {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
Some(unsafe { self.ast().copy(e.to_expression()) })
|
||||
}
|
||||
JSXExpression::EmptyExpression(_) => None,
|
||||
},
|
||||
JSXChild::Element(e) => {
|
||||
|
|
|
|||
|
|
@ -216,14 +216,16 @@ impl<'a> TypeScriptAnnotations<'a> {
|
|||
|
||||
pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
|
||||
if expr.is_typescript_syntax() {
|
||||
*expr = self.ctx.ast.copy(expr.get_inner_expression());
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
*expr = unsafe { self.ctx.ast.copy(expr.get_inner_expression()) };
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_simple_assignment_target(&mut self, target: &mut SimpleAssignmentTarget<'a>) {
|
||||
if let Some(expr) = target.get_expression() {
|
||||
if let Expression::Identifier(ident) = expr.get_inner_expression() {
|
||||
let ident = self.ctx.ast.copy(ident);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
let ident = unsafe { self.ctx.ast.copy(ident) };
|
||||
*target = SimpleAssignmentTarget::AssignmentTargetIdentifier(ident);
|
||||
}
|
||||
}
|
||||
|
|
@ -232,7 +234,8 @@ impl<'a> TypeScriptAnnotations<'a> {
|
|||
pub fn transform_assignment_target(&mut self, target: &mut AssignmentTarget<'a>) {
|
||||
if let Some(expr) = target.get_expression() {
|
||||
if let Some(member_expr) = expr.get_inner_expression().as_member_expression() {
|
||||
*target = AssignmentTarget::from(self.ctx.ast.copy(member_expr));
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
*target = AssignmentTarget::from(unsafe { self.ctx.ast.copy(member_expr) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,7 +238,8 @@ impl<'a> TypeScriptEnum<'a> {
|
|||
let init = match constant_value {
|
||||
None => {
|
||||
prev_constant_value = None;
|
||||
let mut new_initializer = ast.copy(initializer);
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
let mut new_initializer = unsafe { ast.copy(initializer) };
|
||||
|
||||
// If the initializer is a binding identifier,
|
||||
// and it is not a binding in the current scope and parent scopes,
|
||||
|
|
|
|||
|
|
@ -92,7 +92,8 @@ impl<'a> TypeScript<'a> {
|
|||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
self.ctx.ast.expression_from_identifier_reference(ctx.ast.copy(ident))
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
self.ctx.ast.expression_from_identifier_reference(unsafe { ctx.ast.copy(ident) })
|
||||
}
|
||||
TSTypeName::QualifiedName(qualified_name) => self
|
||||
.ctx
|
||||
|
|
|
|||
|
|
@ -45,9 +45,14 @@ impl<'a> TypeScript<'a> {
|
|||
self.ctx.error(namespace_not_supported(decl.span));
|
||||
}
|
||||
|
||||
if let Some(transformed_stmt) =
|
||||
self.handle_nested(self.ctx.ast.copy(&decl).unbox(), None, ctx)
|
||||
{
|
||||
if let Some(transformed_stmt) = self.handle_nested(
|
||||
{
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ctx.ast.copy(&decl) }.unbox()
|
||||
},
|
||||
None,
|
||||
ctx,
|
||||
) {
|
||||
let name = decl.id.name();
|
||||
if names.insert(name.clone()) {
|
||||
new_stmts
|
||||
|
|
@ -68,9 +73,14 @@ impl<'a> TypeScript<'a> {
|
|||
self.ctx.error(namespace_not_supported(decl.span));
|
||||
}
|
||||
|
||||
if let Some(transformed_stmt) =
|
||||
self.handle_nested(self.ctx.ast.copy(decl), None, ctx)
|
||||
{
|
||||
if let Some(transformed_stmt) = self.handle_nested(
|
||||
{
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ctx.ast.copy(decl) }
|
||||
},
|
||||
None,
|
||||
ctx,
|
||||
) {
|
||||
let name = decl.id.name();
|
||||
if names.insert(name.clone()) {
|
||||
let declaration = self.create_variable_declaration(name);
|
||||
|
|
@ -339,7 +349,9 @@ impl<'a> TypeScript<'a> {
|
|||
// (_N.M = {}) or (N = {})
|
||||
let mut logical_right = {
|
||||
// _N.M
|
||||
let assign_left = if let Some(parent_export) = self.ctx.ast.copy(&parent_export) {
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
let parent_export = unsafe { self.ctx.ast.copy(&parent_export) };
|
||||
let assign_left = if let Some(parent_export) = parent_export {
|
||||
self.ctx.ast.simple_assignment_target_member_expression(
|
||||
self.ctx.ast.member_expression_static(
|
||||
SPAN,
|
||||
|
|
@ -464,7 +476,8 @@ impl<'a> TypeScript<'a> {
|
|||
),
|
||||
)
|
||||
.into(),
|
||||
self.ctx.ast.copy(init),
|
||||
// SAFETY: `ast.copy` is unsound! We need to fix.
|
||||
unsafe { self.ctx.ast.copy(init) },
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue