[rust] Tests for HermesParser->ESTree conversion

This commit is contained in:
Joe Savona
2023-08-01 13:55:17 -07:00
parent e353f3702e
commit c09bfff04c
1014 changed files with 191022 additions and 52 deletions
+2
View File
@@ -530,7 +530,9 @@ dependencies = [
"forget_estree",
"forget_estree_codegen",
"hermes",
"insta",
"juno_support",
"serde_json",
]
[[package]]
File diff suppressed because it is too large Load Diff
@@ -542,6 +542,7 @@ Output:
"id": {
"type": "Identifier",
"name": "Component",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -562,6 +563,7 @@ Output:
{
"type": "Identifier",
"name": "props",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -591,6 +593,7 @@ Output:
"id": {
"type": "Identifier",
"name": "x",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -675,6 +678,7 @@ Output:
"id": {
"type": "Identifier",
"name": "i",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -753,6 +757,7 @@ Output:
"left": {
"type": "Identifier",
"name": "i",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -816,6 +821,7 @@ Output:
"argument": {
"type": "Identifier",
"name": "i",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -860,6 +866,7 @@ Output:
"left": {
"type": "Identifier",
"name": "x",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -879,6 +886,7 @@ Output:
"right": {
"type": "Identifier",
"name": "i",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -966,6 +974,7 @@ Output:
"argument": {
"type": "Identifier",
"name": "x",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -121,6 +121,7 @@ Output:
"local": {
"type": "Identifier",
"name": "React",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -203,6 +203,7 @@ Output:
"id": {
"type": "Identifier",
"name": "Component",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -223,6 +224,7 @@ Output:
{
"type": "Identifier",
"name": "props",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -250,6 +252,7 @@ Output:
"object": {
"type": "Identifier",
"name": "props",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -269,6 +272,7 @@ Output:
"property": {
"type": "Identifier",
"name": "value",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -365,6 +365,7 @@ Output:
"id": {
"type": "Identifier",
"name": "foo",
"typeAnnotation": null,
"loc": {
"source": null,
"start": {
@@ -1,6 +1,7 @@
use crate::{
AssignmentPropertyOrRestElement, AssignmentTarget, Class, Declaration, ExportAllDeclaration,
ExportDefaultDeclaration, ExportNamedDeclaration, Expression, ExpressionOrSpread,
AssignmentPropertyOrRestElement, AssignmentTarget, Class, ClassItem, Declaration,
DeclarationOrExpression, ExportAllDeclaration, ExportDefaultDeclaration,
ExportNamedDeclaration, Expression, ExpressionOrPrivateIdentifier, ExpressionOrSpread,
ExpressionOrSuper, ForInInit, ForInit, Function, FunctionBody, Identifier, ImportDeclaration,
ImportDeclarationSpecifier, ImportOrExportDeclaration, Literal, MethodDefinition, ModuleItem,
Pattern, Program, Statement, SwitchCase, VariableDeclarator, _Literal,
@@ -82,7 +83,12 @@ pub trait Visitor<'ast> {
}
fn visit_export_default_declaration(&mut self, declaration: &'ast ExportDefaultDeclaration) {
self.visit_declaration(&declaration.declaration);
match &declaration.declaration {
DeclarationOrExpression::Declaration(declaration) => {
self.visit_declaration(declaration)
}
DeclarationOrExpression::Expression(declaration) => self.visit_expression(declaration),
}
}
fn visit_export_named_declaration(&mut self, declaration: &'ast ExportNamedDeclaration) {
@@ -129,6 +135,9 @@ pub trait Visitor<'ast> {
self.visit_variable_declarator(declarator)
}
}
Declaration::TSTypeAliasDeclaration(declaration) => {
todo!("visit TSTypeAliasDeclaration")
}
}
}
@@ -245,6 +254,9 @@ pub trait Visitor<'ast> {
self.visit_expression(&stmt.object);
self.visit_statement(&stmt.body);
}
Statement::TSTypeAliasDeclaration(stmt) => {
todo!("visit TSTypeAliasDeclaration")
}
}
}
@@ -255,8 +267,19 @@ pub trait Visitor<'ast> {
if let Some(super_class) = &class.super_class {
self.visit_expression(super_class);
}
for method in &class.body.body {
self.visit_method_definition(class, method)
for item in &class.body.body {
match item {
ClassItem::MethodDefinition(item) => self.visit_method_definition(class, item),
ClassItem::ClassProperty(item) => {
todo!("visit ClassProperty")
}
ClassItem::ClassPrivateProperty(item) => {
todo!("visit ClassPrivateProperty")
}
ClassItem::StaticBlock(item) => {
todo!("visit StaticBlock")
}
}
}
}
@@ -395,7 +418,17 @@ pub trait Visitor<'ast> {
ExpressionOrSuper::Expression(object) => self.visit_expression(object),
};
if !expr.is_computed {
self.visit_expression(&expr.property)
match &expr.property {
ExpressionOrPrivateIdentifier::Expression(property) => {
self.visit_expression(property)
}
ExpressionOrPrivateIdentifier::PrivateIdentifier(property) => {
todo!("visit PrivateIdentifier property")
}
ExpressionOrPrivateIdentifier::PrivateName(property) => {
todo!("visit PrivateName property")
}
}
}
}
_ => {
@@ -164,6 +164,10 @@ pub struct Node {
#[serde(default)]
pub skip_hermes_enum_variant: bool,
#[serde(default)]
#[serde(rename = "TODO")]
pub todo: Option<String>,
}
impl Node {
@@ -258,7 +262,9 @@ impl Node {
if let Some(convert_with) = &field.hermes_convert_with {
let convert_with = format_ident!("{}", convert_with);
return quote! {
// println!("read {}.{}", #name_str, #name);
let #field_name = #convert_with(cx, unsafe { hermes::parser::#helper(node) } );
// println!("ok");
}
}
match type_kind {
@@ -266,22 +272,30 @@ impl Node {
match type_name_str.as_ref() {
"bool" => {
quote! {
// println!("read {}.{}", #name_str, #name);
let #field_name = unsafe { hermes::parser::#helper(node) };
// println!("ok");
}
}
"Number" => {
quote! {
// println!("read {}.{}", #name_str, #name);
let #field_name = convert_number(unsafe { hermes::parser::#helper(node) });
// println!("ok");
}
}
"String" => {
quote! {
// println!("read {}.{}", #name_str, #name);
let #field_name = convert_string(cx, unsafe { hermes::parser::#helper(node) });
// println!("ok");
}
}
_ => {
quote! {
// println!("read {}.{}", #name_str, #name);
let #field_name = #type_name::convert(cx, unsafe { hermes::parser::#helper(node) });
// println!("ok");
}
}
}
@@ -290,33 +304,44 @@ impl Node {
match type_name_str.as_ref() {
"String" => {
quote! {
// println!("read {}.{}", #name_str, #name);
let #field_name = convert_option_string(cx, unsafe { hermes::parser::#helper(node) });
// println!("ok");
}
}
_ => {
quote! {
// println!("read {}.{}", #name_str, #name);
let #field_name = convert_option(unsafe { hermes::parser::#helper(node) }, |node| #type_name::convert(cx, node));
// println!("ok");
}
}
}
}
TypeKind::Vec => {
quote! {
// println!("read {}.{}", #name_str, #name);
let #field_name = convert_vec(unsafe { hermes::parser::#helper(node) }, |node| #type_name::convert(cx, node));
// println!("ok");
}
}
TypeKind::VecOfOption => {
quote! {
// println!("read {}.{}", #name_str, #name);
let #field_name = convert_vec_of_option(unsafe { hermes::parser::#helper(node) }, |node| #type_name::convert(cx, node));
// println!("ok");
}
}
}
})
.collect();
let type_ = format_ident!("{}", self.type_.as_ref().unwrap_or(&name_str.to_string()));
quote! {
impl FromHermes for #name {
fn convert(cx: &mut Context, node: NodePtr) -> Self {
let node_ref = node.as_ref();
assert_eq!(node_ref.kind, NodeKind::#type_);
let range = convert_range(node);
#(#fields)*
Self {
@@ -550,6 +575,7 @@ impl Enum {
}
pub fn codegen_hermes(&self, name: &str, grammar: &Grammar) -> TokenStream {
let name_str = name;
let name = format_ident!("{}", name);
let mut tag_matches = Vec::new();
@@ -622,7 +648,7 @@ impl Enum {
let node_ref = node.as_ref();
match node_ref.kind {
#(#tag_matches),*
_ => panic!("Unexpected node")
_ => panic!("Unexpected node kind `{:?}` for `{}`", node_ref.kind, #name_str)
}
}
}
@@ -99,6 +99,13 @@
"type": "Option<Binding>",
"optional": true,
"skip": true
},
"type_annotation": {
"type": "Option<TypeAnnotation>",
"optional": true,
"rename": "typeAnnotation",
"hermes_default": true,
"TODO": "support HermesParser"
}
}
},
@@ -146,6 +153,16 @@
}
}
},
"RegExpLiteral": {
"fields": {
"pattern": {
"type": "String"
},
"flags": {
"type": "String"
}
}
},
"Program": {
"fields": {
"body": {
@@ -381,7 +398,7 @@
"ClassBody": {
"fields": {
"body": {
"type": "Vec<MethodDefinition>"
"type": "Vec<ClassItem>"
}
}
},
@@ -560,7 +577,7 @@
"type": "ExpressionOrSuper"
},
"property": {
"type": "Expression"
"type": "ExpressionOrPrivateIdentifier"
},
"is_computed": {
"type": "bool",
@@ -685,7 +702,7 @@
"ExportDefaultDeclaration": {
"fields": {
"declaration": {
"type": "Declaration"
"type": "DeclarationOrExpression"
}
}
},
@@ -797,6 +814,18 @@
}
}
},
"JSXStringLiteral": {
"fields": {
"value": {
"type": "String",
"hermes_convert_with": "convert_string_value"
},
"raw": {
"type": "String"
}
},
"TODO": "Non-standard HermesParser node"
},
"JSXElement": {
"fields": {
"opening_element": {
@@ -977,7 +1006,82 @@
"type": "Expression"
}
}
}
},
"ClassProperty": {
"fields": {
"key": {
"type": "Expression"
},
"value": {
"type": "Option<Expression>",
"optional": true
},
"is_computed": {
"type": "bool",
"rename": "computed"
},
"is_static": {
"type": "bool",
"rename": "static"
}
}
},
"ClassPrivateProperty": {
"fields": {
"key": {
"type": "ExpressionOrPrivateIdentifier"
},
"value": {
"type": "Option<Expression>",
"optional": true
},
"is_static": {
"type": "bool",
"rename": "static"
}
},
"TODO": "Non-standard HermesParser node"
},
"PrivateName": {
"fields": {
"id": {
"type": "Identifier"
}
},
"TODO": "Non-standard HermesParser node"
},
"PrivateIdentifier": {
"skip_hermes_codegen": true,
"skip_hermes_enum_variant": true,
"fields": {
"name": {
"type": "String"
}
}
},
"StaticBlock": {
"skip_hermes_codegen": true,
"skip_hermes_enum_variant": true,
"fields": {
"body": {
"type": "Vec<Statement>"
}
},
"TODO": "not yet supported in HermesParser"
},
"CoverTypedIdentifier": {
"fields": {
"left": {
"type": "Identifier"
},
"right": {
"type": "Option<TypeAnnotation>"
}
},
"TODO": "Non-standard HermesParser node"
},
"TSTypeAnnotation": {},
"TSTypeAliasDeclaration": {}
},
"enums": {
"Statement": [
@@ -999,6 +1103,7 @@
"SwitchStatement",
"ThrowStatement",
"TryStatement",
"TSTypeAliasDeclaration",
"VariableDeclaration",
"WhileStatement",
"WithStatement"
@@ -1014,10 +1119,12 @@
"ChainExpression",
"ClassExpression",
"ConditionalExpression",
"CoverTypedIdentifier",
"FunctionExpression",
"Identifier",
"ImportExpression",
"JSXElement",
"JSXFragment",
"Literal",
"LogicalExpression",
"MemberExpression",
@@ -1028,6 +1135,7 @@
"ObjectExpression",
"OptionalCallExpression",
"OptionalMemberExpression",
"RegExpLiteral",
"SequenceExpression",
"StringLiteral",
"TaggedTemplateExpression",
@@ -1047,7 +1155,8 @@
"Declaration": [
"ClassDeclaration",
"FunctionDeclaration",
"VariableDeclaration"
"VariableDeclaration",
"TSTypeAliasDeclaration"
],
"ImportDeclarationSpecifier": [
"ImportSpecifier",
@@ -1127,7 +1236,8 @@
"Literal",
"JSXExpressionContainer",
"JSXElement",
"JSXFragment"
"JSXFragment",
"JSXStringLiteral"
],
"JSXElementName": [
"JSXIdentifier",
@@ -1140,10 +1250,29 @@
],
"JSXChildItem": [
"JSXText",
"JSXStringLiteral",
"JSXExpressionContainer",
"JSXSpreadChild",
"JSXElement",
"JSXFragment"
],
"DeclarationOrExpression": [
"Declaration",
"Expression"
],
"ClassItem": [
"MethodDefinition",
"ClassProperty",
"ClassPrivateProperty",
"StaticBlock"
],
"ExpressionOrPrivateIdentifier": [
"Expression",
"PrivateIdentifier",
"PrivateName"
],
"TypeAnnotation": [
"TSTypeAnnotation"
]
},
"operators": {
@@ -140,6 +140,7 @@ fn convert_function(cx: &Context, id: Option<&Ident>, fun: &Function) -> forget_
id: id.map(|id| forget_estree::Identifier {
name: id.sym.to_string(),
binding: convert_binding(cx, id.span.ctxt),
type_annotation: None,
loc: None,
range: convert_span(&id.span),
}),
@@ -767,11 +768,28 @@ fn convert_member_expression(cx: &Context, expr: &MemberExpr) -> forget_estree::
let (is_computed, property) = match &expr.prop {
MemberProp::Ident(prop) => (
false,
forget_estree::Expression::Identifier(Box::new(convert_identifier(cx, prop))),
forget_estree::ExpressionOrPrivateIdentifier::Expression(
forget_estree::Expression::Identifier(Box::new(convert_identifier(cx, prop))),
),
),
MemberProp::Computed(prop) => (true, convert_expression(cx, &prop.expr)),
_ => {
panic!("PrivateName member expression properties are not supported")
MemberProp::Computed(prop) => (
true,
forget_estree::ExpressionOrPrivateIdentifier::Expression(convert_expression(
cx, &prop.expr,
)),
),
MemberProp::PrivateName(prop) => {
let name = prop.id.sym.as_ref().to_string();
(
false,
forget_estree::ExpressionOrPrivateIdentifier::PrivateIdentifier(Box::new(
forget_estree::PrivateIdentifier {
name,
loc: None,
range: convert_span(&prop.span),
},
)),
)
}
};
forget_estree::MemberExpression {
@@ -873,6 +891,7 @@ fn convert_pattern(cx: &Context, pat: &Pat) -> forget_estree::Pattern {
forget_estree::Pattern::Identifier(Box::new(forget_estree::Identifier {
name: pat.id.sym.to_string(),
binding: convert_binding(cx, pat.id.span.ctxt),
type_annotation: None,
loc: None,
range: convert_span(&pat.span),
}))
@@ -897,6 +916,7 @@ fn convert_identifier(cx: &Context, identifier: &Ident) -> forget_estree::Identi
forget_estree::Identifier {
name,
binding: convert_binding(cx, identifier.span.ctxt),
type_annotation: None,
loc: None,
range: convert_span(&identifier.span),
}
@@ -12,10 +12,12 @@ repository.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
insta = { workspace = true }
forget_diagnostics = { workspace = true }
forget_estree = { workspace = true }
hermes = { workspace = true }
juno_support = { workspace = true }
serde_json = { workspace = true }
[build-dependencies]
forget_estree_codegen = { workspace = true }
File diff suppressed because it is too large Load Diff
@@ -1,8 +1,10 @@
use std::num::NonZeroU32;
use forget_estree::{
ArrowFunctionExpression, AssignmentProperty, Class, ClassBody, ClassDeclaration,
ClassExpression, Expression, ExpressionOrSpread, Function, FunctionBody, FunctionDeclaration,
FunctionExpression, Identifier, Number, Pattern, SourceRange, TemplateElement,
TemplateElementValue,
ClassExpression, ClassPrivateProperty, Expression, ExpressionOrSpread, Function, FunctionBody,
FunctionDeclaration, FunctionExpression, Identifier, Number, Pattern, SourceRange,
TemplateElement, TemplateElementValue,
};
use hermes::parser::{
hermes_get_ArrowFunctionExpression_async, hermes_get_ArrowFunctionExpression_body,
@@ -68,7 +70,10 @@ where
pub fn convert_range(node: NodePtr) -> SourceRange {
let _range = node.as_ref().source_range;
todo!()
SourceRange {
start: 0,
end: NonZeroU32::new(1).unwrap(),
}
}
#[allow(dead_code)]
@@ -0,0 +1,11 @@
function Component() {
// a's mutable range should be the same as x's mutable range,
// since a is captured into x (which gets mutated later)
let a = someObj();
let x = [];
x.push(a);
mutate(x);
return [x, a];
}
@@ -0,0 +1,10 @@
function Component() {
// a's mutable range should be limited
// the following line
let a = someObj();
let x = [];
x.push(a);
return [x, a];
}
@@ -0,0 +1,8 @@
function component(a) {
let x = { a };
let y = {};
y.x = x["a"];
mutate(y);
return x;
}
@@ -0,0 +1,9 @@
function component() {
let z = [];
let y = {};
y.z = z;
let x = {};
x.y = y;
mutate(x.y.z);
return x;
}
@@ -0,0 +1,8 @@
function component() {
let z = [];
let y = {};
y.z = z;
let x = {};
x.y = y;
return x;
}
@@ -0,0 +1,18 @@
function foo(cond) {
let a = {};
let b = {};
let c = {};
while (cond) {
let z = a;
a = b;
b = c;
c = z;
mutate(a, b);
}
a;
b;
c;
return a;
}
function mutate(x, y) {}
@@ -0,0 +1,11 @@
// bar(props.b) is an allocating expression that produces a primitive, which means
// that Forget should memoize it.
// Correctness:
// - y depends on either bar(props.b) or bar(props.b) + 1
function AllocatingPrimitiveAsDepNested(props) {
let x = {};
mutate(x);
let y = foo(bar(props.b) + 1);
mutate(x, props.a);
return [x, y];
}
@@ -0,0 +1,8 @@
// bar(props.b) is an allocating expression that produces a primitive, which means
// that Forget should memoize it.
// Correctness:
// - y depends on either bar(props.b) or bar(props.b) + 1
function AllocatingPrimitiveAsDep(props) {
let y = foo(bar(props).b + 1);
return y;
}
@@ -0,0 +1,4 @@
function Component(props) {
const ref = useRef(null);
return <Foo ref={ref} />;
}
@@ -0,0 +1,8 @@
function foo(a, b, c) {
const x = [a];
const y = [null, b];
const z = [[], [], [c]];
x[0] = y[1];
z[0][0] = x[0];
return [x, z];
}
@@ -0,0 +1,9 @@
function Component(props) {
const x = foo(props.x);
const fn = function () {
const arr = [...bar(props)];
return arr.at(x);
};
const fnResult = fn();
return fnResult;
}
@@ -0,0 +1,9 @@
// arrayInstance.at should have the following effects:
// - read on arg0
// - read on receiver
// - mutate on lvalue
function ArrayAtTest(props) {
const arr = [foo(props.x)];
const result = arr.at(bar(props.y));
return result;
}
@@ -0,0 +1,10 @@
// x's mutable range should extend to `mutate(y)`
function Component(props) {
let x = [42, {}];
const idx = foo(props.b);
let y = x.at(idx);
mutate(y);
return x;
}
@@ -0,0 +1,4 @@
function Component(props) {
const x = [0, ...props.foo, null, ...props.bar, "z"];
return x;
}
@@ -0,0 +1,6 @@
function Component(props) {
const x = [{}, [], props.value];
const y = x.join(() => "this closure gets stringified, not called");
foo(y);
return [x, y];
}
@@ -0,0 +1,6 @@
function Component(props) {
const x = [];
<dif>{x}</dif>;
const y = x.map((item) => item);
return [x, y];
}
@@ -0,0 +1,8 @@
function Component(props) {
const x = [];
const y = x.map((item) => {
item.updated = true;
return item;
});
return [x, y];
}
@@ -0,0 +1,5 @@
function component([a, b]) {
let y = { a };
let z = { b };
return [y, z];
}
@@ -0,0 +1,6 @@
function Component(props) {
const a = [props.a, props.b, "hello"];
const x = a.length;
const y = a.push;
return { a, x, y, z: a.concat };
}
@@ -0,0 +1,7 @@
function Component(props) {
const a = [props.a, props.b, "hello"];
const x = a.push(42);
const y = a.at(props.c);
return { a, x, y };
}
@@ -0,0 +1,11 @@
// arrayInstance.push should have the following effects:
// - read on all args (rest parameter)
// - mutate on receiver
function Component(props) {
const x = foo(props.x);
const y = { y: props.y };
const arr = [];
arr.push({});
arr.push(x, y);
return arr;
}
@@ -0,0 +1,4 @@
// @gating
const ErrorView = (error, _retry) => <MessageBox error={error}></MessageBox>;
export default ErrorView;
@@ -0,0 +1,7 @@
function Component(props) {
const x = [props.x];
const index = 0;
x[index] *= 2;
x["0"] += 3;
return x;
}
@@ -0,0 +1,6 @@
function g(props) {
const a = { b: { c: props.c } };
a.b.c = a.b.c + 1;
a.b.c *= 2;
return a;
}
@@ -0,0 +1,11 @@
function useBar(props) {
let z;
if (props.a) {
if (props.b) {
z = baz();
}
}
return z;
}
@@ -0,0 +1,6 @@
function foo() {
const a = [[1]];
const first = a.at(0);
first.set(0, 2);
return a;
}
@@ -0,0 +1,6 @@
function g() {
const x = { y: { z: 1 } };
x.y.z = x.y.z + 1;
x.y.z *= 2;
return x;
}
@@ -0,0 +1,7 @@
function f() {
let x = 1;
x = x + 1;
x += 1;
x >>>= 1;
return x;
}
@@ -0,0 +1,5 @@
async function Component(props) {
const x = [];
await populateData(props.id, x);
return x;
}
@@ -0,0 +1,4 @@
async function Component(props) {
const user = await load(props.id);
return <div>{user.name}</div>;
}
@@ -0,0 +1,15 @@
import { useState, useMemo } from "react";
function Component(props) {
const [x] = useState(0);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
function Component2(props) {
const [x] = useState(0);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
@@ -0,0 +1,16 @@
import * as React from "react";
import { useState, useMemo } from "react";
function Component(props) {
const [x] = useState(0);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
function Component2(props) {
const [x] = useState(0);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
@@ -0,0 +1,9 @@
function App({ text, hasDeps }) {
const resolvedText = useMemo(
() => {
return text.toUpperCase();
},
hasDeps ? null : [text] // should be DCE'd
);
return resolvedText;
}
@@ -0,0 +1,5 @@
function component(t) {
let { a } = t;
let y = { a };
return y;
}
@@ -0,0 +1,4 @@
function Component(props) {
const maybeMutable = new MaybeMutable();
return <div>{maybeMutate(maybeMutable)}</div>;
}
@@ -0,0 +1,5 @@
function Component(props) {
let x = makeObject();
x.foo((x = makeObject()));
return x;
}
@@ -0,0 +1,5 @@
function Component(props) {
let x = makeObject();
x.foo(([x] = makeObject()));
return x;
}
@@ -0,0 +1,4 @@
function Component(props) {
const x = foo(...props.a, null, ...props.b);
return x;
}
@@ -0,0 +1,9 @@
function Component(props) {
const x = makeFunction(props);
const y = x(
<div>
<span>{props.text}</span>
</div>
);
return y;
}
@@ -0,0 +1,10 @@
function foo() {}
function Component(props) {
const a = [];
const b = {};
foo(a, b);
let _ = <div a={a} />;
foo(b);
return <div a={a} b={b} />;
}
@@ -0,0 +1,11 @@
function component(a) {
let x = { a };
(function () {
let q = x;
(function () {
q.b = 1;
})();
})();
return x;
}
@@ -0,0 +1,37 @@
function getNativeLogFunction(level) {
return function () {
let str;
if (arguments.length === 1 && typeof arguments[0] === "string") {
str = arguments[0];
} else {
str = Array.prototype.map
.call(arguments, function (arg) {
return inspect(arg, {
depth: 10,
});
})
.join(", ");
}
const firstArg = arguments[0];
let logLevel = level;
if (
typeof firstArg === "string" &&
firstArg.slice(0, 9) === "Warning: " &&
logLevel >= LOG_LEVELS.error
) {
logLevel = LOG_LEVELS.warn;
}
if (global.__inspectorLog) {
global.__inspectorLog(
INSPECTOR_LEVELS[logLevel],
str,
[].slice.call(arguments),
INSPECTOR_FRAMES_TO_SKIP
);
}
if (groupStack.length) {
str = groupFormat("", str);
}
global.nativeLoggingHook(str, logLevel);
};
}
@@ -0,0 +1,9 @@
function component(a) {
let z = { a };
(function () {
(function () {
z.b = 1;
})();
})();
return z;
}
@@ -0,0 +1,7 @@
function component(a) {
let z = { a };
let x = () => {
console.log(z);
};
return x;
}
@@ -0,0 +1,11 @@
function component(foo, bar) {
let x = { foo };
let y = { bar };
(function () {
let a = { y };
let b = x;
a.x = b;
})();
mutate(y);
return x;
}
@@ -0,0 +1,11 @@
function component(foo, bar) {
let x = { foo };
let y = { bar };
(function () {
let a = [y];
let b = x;
a.x = b;
})();
mutate(y);
return x;
}
@@ -0,0 +1,11 @@
function component(foo, bar) {
let x = { foo };
let y = { bar };
(function () {
let a = [y];
let b = x;
a.x = b;
})();
mutate(y);
return y;
}
@@ -0,0 +1,11 @@
function component(foo, bar) {
let x = { foo };
let y = { bar };
(function () {
let a = { y };
let b = x;
a.x = b;
})();
mutate(y);
return y;
}
@@ -0,0 +1,9 @@
function component(a) {
let x = { a };
let y = {};
(function () {
y["x"] = x;
})();
mutate(y);
return y;
}
@@ -0,0 +1,9 @@
function component(a) {
let x = { a };
let y = {};
(function () {
y.x = x;
})();
mutate(y);
return y;
}
@@ -0,0 +1,10 @@
function component(a) {
let x = { a };
let y = {};
(function () {
let a = y;
a["x"] = x;
})();
mutate(y);
return y;
}
@@ -0,0 +1,10 @@
function component(a) {
let x = { a };
let y = {};
(function () {
let a = y;
a.x = x;
})();
mutate(y);
return y;
}
@@ -0,0 +1,10 @@
function component(a, b) {
let y = { b };
let z = { a };
let x = function () {
z.a = 2;
y.b;
};
x();
return z;
}
@@ -0,0 +1,9 @@
function component(a, b) {
let y = { b };
let z = { a };
let x = function () {
z.a = 2;
y.b;
};
return z;
}
@@ -0,0 +1,8 @@
function component(a) {
let y = { b: { a } };
let x = function () {
y.b.a = 2;
};
x();
return y;
}
@@ -0,0 +1,10 @@
function component(a, b) {
let z = { a };
let y = { b };
let x = function () {
z.a = 2;
console.log(y.b);
};
x();
return z;
}
@@ -0,0 +1,9 @@
function component(a) {
let x = { a };
let y = {};
(function () {
y = x;
})();
mutate(y);
return y;
}
@@ -0,0 +1,7 @@
function component(a) {
let z = { a };
let x = function () {
console.log(z);
};
return x;
}
@@ -0,0 +1,9 @@
function bar(a) {
let x = [a];
let y = {};
(function () {
y = x[0][1];
})();
return y;
}
@@ -0,0 +1,11 @@
function bar(a, b) {
let x = [a, b];
let y = {};
let t = {};
(function () {
y = x[0][1];
t = x[1][0];
})();
return y;
}
@@ -0,0 +1,9 @@
function bar(a) {
let x = [a];
let y = {};
(function () {
y = x[0].a[1];
})();
return y;
}
@@ -0,0 +1,9 @@
function bar(a) {
let x = [a];
let y = {};
(function () {
y = x[0];
})();
return y;
}
@@ -0,0 +1,14 @@
function component(a, b) {
let z = { a };
(function () {
mutate(z);
})();
let y = z;
{
// z is shadowed & renamed but the lambda is unaffected.
let z = { b };
y = { y, z };
}
return y;
}
@@ -0,0 +1,14 @@
// @debug
function component(a, b) {
let z = { a };
let y = b;
let x = function () {
if (y) {
// we don't know for sure this mutates, so we should assume
// that there is no mutation so long as `x` isn't called
// during render
maybeMutate(z);
}
};
return x;
}
@@ -0,0 +1,8 @@
function component(a) {
let t = { a };
function x() {
t.foo();
}
x(t);
return t;
}
@@ -0,0 +1,10 @@
function Foo(props) {
const onFoo = useCallback(
(reason) => {
log(props.router.location);
},
[props.router.location]
);
return onFoo;
}
@@ -0,0 +1,11 @@
function component({ mutator }) {
const poke = () => {
mutator.poke();
};
const hide = () => {
mutator.user.hide();
};
return <Foo poke={poke} hide={hide}></Foo>;
}
@@ -0,0 +1,10 @@
function component(a, b) {
let z = { a };
{
let z = { b };
(function () {
mutate(z);
})();
}
return z;
}
@@ -0,0 +1,5 @@
function component(a, b) {
let z = { a };
let p = () => <Foo>{z}</Foo>;
return p();
}
@@ -0,0 +1,8 @@
function component(a) {
let z = { a };
let x = function () {
let z;
mutate(z);
};
return x;
}
@@ -0,0 +1,4 @@
function StoreLandingUnseenGiftModalContainer(a) {
const giftsSeen = { a };
return ((gift) => (gift.id ? giftsSeen[gift.id] : false))();
}
@@ -0,0 +1,10 @@
function component(a) {
let z = { a };
let x;
{
x = function () {
console.log(z);
};
}
return x;
}
@@ -0,0 +1,7 @@
function component(a) {
let z = { a };
let x = function () {
console.log(z.a);
};
return x;
}
@@ -0,0 +1,7 @@
function component(a) {
let z = { a: { a } };
let x = function () {
z.a.a();
};
return z;
}
@@ -0,0 +1,9 @@
function component(a) {
let z = { a: { a } };
let x = function () {
(function () {
console.log(z.a.a);
})();
};
return x;
}
@@ -0,0 +1,7 @@
function component(a) {
let z = { a: { a } };
let x = function () {
console.log(z.a.a);
};
return x;
}
@@ -0,0 +1,9 @@
function component(a) {
let x = { a };
let y = 1;
(function () {
y = x;
})();
mutate(y);
return y;
}
@@ -0,0 +1,9 @@
function component(a) {
let z = { a };
let x = function () {
{
console.log(z);
}
};
return x;
}
@@ -0,0 +1,9 @@
function component(a) {
let z = { a };
let x = function () {
(function () {
console.log(z);
})();
};
return x;
}
@@ -0,0 +1,9 @@
function Component() {
let x,
y = (x = {});
const foo = () => {
x = getObject();
};
foo();
return [y, x];
}
@@ -0,0 +1,8 @@
function foo() {
const x = { x: 0 };
const y = { z: 0 };
const z = { z: 0 };
x.x += y.y *= 1;
z.z += y.y *= x.x &= 3;
return z;
}
@@ -0,0 +1,5 @@
// @enableEmitFreeze @instrumentForget
function useFoo(props) {
return foo(props.x);
}
@@ -0,0 +1,11 @@
// @enableEmitFreeze true
function MyComponentName(props) {
let x = {};
foo(x, props.a);
foo(x, props.b);
let y = [];
y.push(x);
return y;
}
@@ -0,0 +1,15 @@
// @instrumentForget @forgetDirective @gating
function Bar(props) {
"use forget";
return <div>{props.bar}</div>;
}
function NoForget(props) {
return <Bar>{props.noForget}</Bar>;
}
function Foo(props) {
"use forget";
return <Foo>{props.bar}</Foo>;
}
@@ -0,0 +1,15 @@
// @instrumentForget @forgetDirective
function Bar(props) {
"use forget";
return <div>{props.bar}</div>;
}
function NoForget(props) {
return <Bar>{props.noForget}</Bar>;
}
function Foo(props) {
"use forget";
return <Foo>{props.bar}</Foo>;
}
@@ -0,0 +1,10 @@
function foo(a, b, c) {
label: if (a) {
while (b) {
if (c) {
break label;
}
}
}
return c;
}
@@ -0,0 +1,26 @@
function Component(props) {
const items = props.items;
const maxItems = props.maxItems;
const renderedItems = [];
const seen = new Set();
const max = Math.max(0, maxItems);
for (let i = 0; i < items.length; i += 1) {
const item = items.at(i);
if (item == null || seen.has(item)) {
continue;
}
seen.add(item);
renderedItems.push(<div>{item}</div>);
if (renderedItems.length >= max) {
break;
}
}
const count = renderedItems.length;
return (
<div>
<h1>{count} Items</h1>
{renderedItems}
</div>
);
}

Some files were not shown because too many files have changed in this diff Show More