feat(es/estree): Allow emitting acorn ast (#2859)

swc_estree_ast:
 - Add `Flavor`.
 - Adjust serialization based on `Flavor`.

swc_estree_visit:
 - Remove.

testing:
 - Add `diff_json`.

testing_macros:
 - `#[fixture]`: Print input.
This commit is contained in:
Donny/강동윤 2021-11-25 20:16:46 +09:00 committed by GitHub
parent 730e138925
commit cdef843369
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
120 changed files with 6232 additions and 2720 deletions

View File

@ -153,8 +153,6 @@ jobs:
- swc_eq_ignore_macros
- swc_estree_ast
- swc_estree_compat
- swc_estree_macros
- swc_estree_visit
- swc_fast_graph
- swc_graph_analyzer
- swc_macros_common

30
Cargo.lock generated
View File

@ -3143,18 +3143,18 @@ dependencies = [
[[package]]
name = "swc_estree_ast"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"scoped-tls",
"serde",
"serde_json",
"swc_atoms 0.2.9",
"swc_common",
"swc_estree_macros",
]
[[package]]
name = "swc_estree_compat"
version = "0.2.1"
version = "0.3.0"
dependencies = [
"ahash",
"anyhow",
@ -3172,29 +3172,12 @@ dependencies = [
"swc_ecma_utils",
"swc_ecma_visit",
"swc_estree_ast",
"swc_estree_macros",
"swc_estree_visit",
"swc_node_base",
"swc_node_comments",
"testing",
"walkdir",
]
[[package]]
name = "swc_estree_macros"
version = "0.1.0"
[[package]]
name = "swc_estree_visit"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
"swc_atoms 0.2.9",
"swc_estree_ast",
"swc_estree_macros",
"swc_visit",
]
[[package]]
name = "swc_fast_graph"
version = "0.1.0"
@ -3412,13 +3395,14 @@ dependencies = [
[[package]]
name = "testing"
version = "0.15.1"
version = "0.15.2"
dependencies = [
"ansi_term 0.12.1",
"difference",
"once_cell",
"pretty_assertions 0.7.2",
"regex",
"serde_json",
"swc_common",
"testing_macros",
"tracing",
@ -3427,7 +3411,7 @@ dependencies = [
[[package]]
name = "testing_macros"
version = "0.2.3"
version = "0.2.4"
dependencies = [
"anyhow",
"glob",

View File

@ -78,8 +78,6 @@ impl Visit for AssertValid {
#[testing::fixture("tests/fixture/**/input.css")]
fn tokens_input(input: PathBuf) {
eprintln!("Input: {}", input.display());
testing::run_test2(false, |cm, handler| {
let fm = cm.load_file(&input).unwrap();
@ -125,8 +123,6 @@ fn tokens_input(input: PathBuf) {
}
fn test_pass(input: PathBuf, config: ParserConfig) {
eprintln!("Input: {}", input.display());
testing::run_test2(false, |cm, handler| {
let ref_json_path = input.parent().unwrap().join("output.json");
@ -230,7 +226,6 @@ fn line_commetns(input: PathBuf) {
#[testing::fixture("tests/recovery/**/input.css")]
fn recovery(input: PathBuf) {
eprintln!("Input: {}", input.display());
let stderr_path = input.parent().unwrap().join("output.swc-stderr");
let mut errored = false;
@ -427,7 +422,6 @@ impl Visit for SpanVisualizer<'_> {
#[testing::fixture("tests/fixture/**/input.css")]
fn span(input: PathBuf) {
eprintln!("Input: {}", input.display());
let dir = input.parent().unwrap().to_path_buf();
let output = testing::run_test2(false, |cm, handler| {
@ -475,7 +469,6 @@ fn span(input: PathBuf) {
#[testing::fixture("tests/errors/**/input.css")]
fn fail(input: PathBuf) {
eprintln!("Input: {}", input.display());
let stderr_path = input.parent().unwrap().join("output.stderr");
let stderr = testing::run_test2(false, |cm, handler| -> Result<(), _> {

View File

@ -6,18 +6,14 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_estree_ast"
repository = "https://github.com/swc-project/swc.git"
version = "0.1.0"
version = "0.2.0"
[package.metadata.docs.rs]
all-features = true
[features]
flavor-acorn = []
flavor-babel = []
[dependencies]
scoped-tls = "1.0.0"
serde = {version = "1", features = ["derive"]}
serde_json = "1.0.62"
serde_json = "1"
swc_atoms = {version = "0.2", path = "../swc_atoms"}
swc_common = {version = "0.14", path = "../swc_common"}
swc_estree_macros = {version = "0.1", path = "../swc_estree_macros/"}

View File

@ -1,18 +1,18 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;
use swc_common::ast_serde;
use crate::{
common::{
Access, BaseNode, Decorator, Identifier, Param, PrivateName, SuperTypeParams,
TypeAnnotOrNoop, TypeParamDeclOrNoop,
},
expr::{ClassExpression, Expression},
flavor::Flavor,
flow::{ClassImplements, InterfaceExtends},
object::ObjectKey,
stmt::{BlockStatement, Statement},
typescript::{TSDeclareMethod, TSExpressionWithTypeArguments, TSIndexSignature},
};
use serde::{ser::SerializeMap, Deserialize, Serialize};
use serde_json::Value;
use swc_common::ast_serde;
#[derive(Debug, Clone, PartialEq)]
#[ast_serde]
@ -32,8 +32,7 @@ pub enum ClassMethodKind {
Constructor,
}
#[derive(Debug, Clone, PartialEq)]
#[ast_serde("ClassMethod")]
#[derive(Debug, Clone, PartialEq, Deserialize)]
pub struct ClassMethod {
#[serde(flatten)]
pub base: BaseNode,
@ -45,17 +44,32 @@ pub struct ClassMethod {
pub body: BlockStatement,
#[serde(default)]
pub computed: Option<bool>,
#[serde(default, rename = "static")]
#[serde(
default,
rename = "static",
skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
)]
pub is_static: Option<bool>,
#[serde(default)]
#[serde(
default,
skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
)]
pub generator: Option<bool>,
#[serde(default, rename = "async")]
#[serde(
default,
rename = "async",
serialize_with = "crate::ser::serialize_as_bool"
)]
pub is_async: Option<bool>,
#[serde(default, rename = "abstract")]
#[serde(
default,
rename = "abstract",
skip_serializing_if = "crate::flavor::Flavor::skip_none"
)]
pub is_abstract: Option<bool>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub access: Option<Access>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub accessibility: Option<Access>,
#[serde(default)]
pub decorators: Option<Vec<Decorator>>,
@ -67,6 +81,134 @@ pub struct ClassMethod {
pub type_parameters: Option<TypeParamDeclOrNoop>,
}
#[derive(Serialize)]
struct BabelClassMethod<'a> {
#[serde(rename = "type")]
type_: &'a str,
#[serde(flatten)]
pub base: &'a BaseNode,
#[serde(default)]
pub kind: Option<ClassMethodKind>,
pub key: &'a ObjectKey,
#[serde(default)]
pub params: &'a [Param],
pub body: &'a BlockStatement,
#[serde(default)]
pub computed: Option<bool>,
#[serde(
default,
rename = "static",
skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
)]
pub is_static: Option<bool>,
#[serde(
default,
skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
)]
pub generator: Option<bool>,
#[serde(
default,
rename = "async",
serialize_with = "crate::ser::serialize_as_bool"
)]
pub is_async: Option<bool>,
#[serde(
default,
rename = "abstract",
skip_serializing_if = "crate::flavor::Flavor::skip_none"
)]
pub is_abstract: Option<bool>,
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub access: Option<&'a Access>,
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub accessibility: Option<&'a Access>,
#[serde(default)]
pub decorators: Option<&'a [Decorator]>,
#[serde(default)]
pub optional: Option<bool>,
#[serde(default)]
pub return_type: Option<&'a TypeAnnotOrNoop>,
#[serde(default)]
pub type_parameters: Option<&'a TypeParamDeclOrNoop>,
}
#[derive(Serialize)]
struct AcornClassMethodValue<'a> {
/// `FuncionExpression`
#[serde(rename = "type")]
type_: &'a str,
#[serde(flatten)]
base: &'a BaseNode,
body: &'a BlockStatement,
params: &'a [Param],
generator: bool,
#[serde(rename = "async")]
is_async: bool,
}
impl Serialize for ClassMethod {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match Flavor::current() {
Flavor::Babel => {
let actual = BabelClassMethod {
type_: "ClassMethod",
base: &self.base,
kind: self.kind,
key: &self.key,
params: &self.params,
body: &self.body,
computed: self.computed,
is_static: self.is_static,
generator: self.generator,
is_async: self.is_async,
is_abstract: self.is_abstract,
access: self.access.as_ref(),
accessibility: self.accessibility.as_ref(),
decorators: self.decorators.as_deref(),
optional: self.optional,
return_type: self.return_type.as_deref(),
type_parameters: self.type_parameters.as_ref(),
};
actual.serialize(serializer)
}
Flavor::Acorn => {
let mut s = serializer.serialize_map(None)?;
{
// TODO(kdy1): This is bad.
self.base
.serialize(serde::__private::ser::FlatMapSerializer(&mut s))?;
}
s.serialize_entry("type", "MethodDefinition")?;
s.serialize_entry("computed", &self.computed.unwrap_or(false))?;
s.serialize_entry("key", &self.key)?;
s.serialize_entry("kind", &self.kind)?;
s.serialize_entry("static", &self.is_static.unwrap_or(false))?;
s.serialize_entry(
"value",
&AcornClassMethodValue {
type_: "FunctionExpression",
base: &self.body.base,
body: &self.body,
params: &self.params,
generator: self.generator.unwrap_or(false),
is_async: self.is_async.unwrap_or(false),
},
)?;
s.end()
}
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[ast_serde("ClassPrivateProperty")]
pub struct ClassPrivateProperty {
@ -209,19 +351,23 @@ pub struct ClassDeclaration {
#[serde(default)]
pub super_class: Option<Box<Expression>>,
pub body: ClassBody,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub decorators: Option<Vec<Decorator>>,
#[serde(default, rename = "abstract")]
#[serde(
default,
rename = "abstract",
skip_serializing_if = "crate::ser::skip_typescript"
)]
pub is_abstract: Option<bool>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::ser::skip_typescript")]
pub declare: Option<bool>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub implements: Option<Vec<ClassImpl>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub mixins: Option<InterfaceExtends>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub super_type_parameters: Option<SuperTypeParams>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_parameters: Option<TypeParamDeclOrNoop>,
}

View File

@ -1,11 +1,18 @@
use crate::common::Loc;
use serde::{Deserialize, Serialize};
use swc_common::ast_serde;
use crate::common::Loc;
#[derive(Debug, Clone, PartialEq)]
#[ast_serde("BaseComment")]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CommentType {
#[serde(rename = "CommentLine")]
Line,
#[serde(rename = "CommentBlock")]
Block,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BaseComment {
#[serde(rename = "type")]
pub type_: CommentType,
pub value: String,
pub start: usize,
pub end: usize,

View File

@ -38,23 +38,23 @@ impl Loc {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct BaseNode {
#[serde(default)]
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub leading_comments: Vec<Comment>,
#[serde(default)]
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub inner_comments: Vec<Comment>,
#[serde(default)]
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub trailing_comments: Vec<Comment>,
#[serde(default)]
pub start: Option<usize>,
#[serde(default)]
pub end: Option<usize>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_range")]
pub range: Option<[usize; 2]>,
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_loc")]
pub loc: Option<Loc>,
/* TODO(dwoznicki): I can't figure out what goes in this field, so I'm just
* removing it for now.
* #[serde(default)]
* pub extra: Option<HashMap<String, Value, RandomState>>, */
}
#[derive(Debug, Clone, PartialEq)]
@ -113,15 +113,12 @@ pub enum FunctionParent {
#[ast_serde]
pub enum Immutable {
#[tag("StringLiteral")]
StringLiteral(StringLiteral),
#[tag("DecimalLiteral")]
#[tag("NumericLiteral")]
NumericLiteral(NumericLiteral),
#[tag("NullLiteral")]
NullLiteral(NullLiteral),
#[tag("BooleanLiteral")]
BooleanLiteral(BooleanLiteral),
#[tag("BigIntLiteral")]
BigIntLiteral(BigIntLiteral),
Literal(Literal),
#[tag("JSXAttribute")]
JSXAttribute(JSXAttribute),
#[tag("JSXClosingElement")]
@ -142,8 +139,6 @@ pub enum Immutable {
JSXOpeningFragment(JSXOpeningFragment),
#[tag("JSXClosingFragment")]
JSXClosingFragment(JSXClosingFragment),
#[tag("DecimalLiteral")]
DecimalLiteral(DecimalLiteral),
}
#[derive(Debug, Clone, PartialEq)]
@ -187,21 +182,15 @@ pub enum Pureish {
#[tag("FunctionExpression")]
FunctionExpr(FunctionExpression),
#[tag("StringLiteral")]
StringLiteral(StringLiteral),
#[tag("NumericLiteral")]
NumericLiteral(NumericLiteral),
#[tag("NullLiteral")]
NullLiteral(NullLiteral),
#[tag("BooleanLiteral")]
BooleanLiteral(BooleanLiteral),
#[tag("RegExpLiteral")]
RegExpLiteral(RegExpLiteral),
#[tag("BigIntLiteral")]
#[tag("DecimalLiteral")]
Literal(Literal),
#[tag("ArrowFunctionExpression")]
ArrowFuncExpr(ArrowFunctionExpression),
#[tag("BigIntLiteral")]
BigIntLiteral(BigIntLiteral),
#[tag("DecimalLiteral")]
DecimalLiteral(DecimalLiteral),
}
#[derive(Debug, Clone, PartialEq)]
@ -346,9 +335,9 @@ pub struct RestElement {
#[serde(flatten)]
pub base: BaseNode,
pub argument: Box<LVal>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub decorators: Option<Vec<Decorator>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_annotation: Option<Box<TypeAnnotOrNoop>>,
}
@ -372,11 +361,14 @@ pub struct Identifier {
pub base: BaseNode,
#[serde(default)]
pub name: JsWord,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub decorators: Option<Vec<Decorator>>,
#[serde(default)]
#[serde(
default,
skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
)]
pub optional: Option<bool>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_annotation: Option<Box<TypeAnnotOrNoop>>,
}

View File

@ -94,7 +94,10 @@ pub struct VariableDeclarator {
pub id: LVal,
#[serde(default)]
pub init: Option<Box<Expression>>,
#[serde(default)]
#[serde(
default,
skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
)]
pub definite: Option<bool>,
}
@ -106,7 +109,10 @@ pub struct VariableDeclaration {
pub kind: VariableDeclarationKind,
#[serde(default)]
pub declarations: Vec<VariableDeclarator>,
#[serde(default)]
#[serde(
default,
skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
)]
pub declare: Option<bool>,
}
@ -124,9 +130,11 @@ pub struct FunctionDeclaration {
pub generator: Option<bool>,
#[serde(default, rename = "async")]
pub is_async: Option<bool>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::ser::skip_expression_for_fn")]
pub expression: bool,
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub return_type: Option<Box<TypeAnnotOrNoop>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_parameters: Option<TypeParamDeclOrNoop>,
}
@ -139,6 +147,7 @@ impl From<FunctionExpression> for FunctionDeclaration {
body: expr.body,
generator: expr.generator,
is_async: expr.is_async,
expression: false,
return_type: expr.return_type,
type_parameters: expr.type_parameters,
}

View File

@ -8,10 +8,7 @@ use crate::{
InterfaceExtends, TypeAnnotation, TypeParameterDeclaration, TypeParameterInstantiation,
},
jsx::{JSXElement, JSXFragment, JSXNamespacedName},
lit::{
BigIntLiteral, BooleanLiteral, DecimalLiteral, NullLiteral, NumericLiteral, RegExpLiteral,
StringLiteral, TemplateLiteral,
},
lit::{Literal, TemplateLiteral},
module::{Import, Program},
object::{ObjectMethod, ObjectProperty},
stmt::{BlockStatement, ExpressionStatement},
@ -41,15 +38,13 @@ pub enum Expression {
#[tag("Identifier")]
Id(Identifier),
#[tag("StringLiteral")]
StringLiteral(StringLiteral),
#[tag("NumericLiteral")]
NumericLiteral(NumericLiteral),
#[tag("NullLiteral")]
NullLiteral(NullLiteral),
#[tag("BooleanLiteral")]
BooleanLiteral(BooleanLiteral),
#[tag("RegExpLiteral")]
RegExpLiteral(RegExpLiteral),
#[tag("DecimalLiteral")]
#[tag("BigIntLiteral")]
Literal(Literal),
#[tag("LogicalExpression")]
Logical(LogicalExpression),
#[tag("MemberExpression")]
@ -86,8 +81,6 @@ pub enum Expression {
Await(AwaitExpression),
#[tag("Import")]
Import(Import),
#[tag("BigIntLiteral")]
BigIntLiteral(BigIntLiteral),
#[tag("OptionalMemberExpression")]
OptionalMember(OptionalMemberExpression),
#[tag("OptionalCallExpression")]
@ -108,8 +101,6 @@ pub enum Expression {
Record(RecordExpression),
#[tag("TupleExpression")]
Tuple(TupleExpression),
#[tag("DecimalLiteral")]
DecimalLiteral(DecimalLiteral),
#[tag("ModuleExpression")]
Module(ModuleExpression),
#[tag("TSAsExpression")]
@ -180,7 +171,7 @@ pub struct MemberExpression {
pub property: Box<MemberExprProp>,
#[serde(default)]
pub computed: bool,
#[serde(default)]
#[serde(default, serialize_with = "crate::ser::serialize_optional")]
pub optional: Option<bool>,
}
@ -313,11 +304,11 @@ pub struct CallExpression {
pub callee: Box<Callee>,
#[serde(default)]
pub arguments: Vec<Arg>,
#[serde(default)]
#[serde(default, serialize_with = "crate::ser::serialize_optional")]
pub optional: Option<bool>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_arguments: Option<TypeParameterInstantiation>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_parameters: Option<TSTypeParameterInstantiation>,
}
@ -345,9 +336,9 @@ pub struct FunctionExpression {
pub generator: Option<bool>,
#[serde(default, rename = "async")]
pub is_async: Option<bool>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub return_type: Option<Box<TypeAnnotOrNoop>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_parameters: Option<TypeParamDeclOrNoop>,
}
@ -359,11 +350,14 @@ pub struct NewExpression {
pub callee: Callee,
#[serde(default)]
pub arguments: Vec<Arg>,
#[serde(default)]
#[serde(
default,
skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
)]
pub optional: Option<bool>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_arguments: Option<TypeParameterInstantiation>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_parameters: Option<TSTypeParameterInstantiation>,
}
@ -508,9 +502,9 @@ pub struct ArrowFunctionExpression {
pub expression: bool,
#[serde(default)]
pub generator: bool,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub return_type: Option<Box<TypeAnnotOrNoop>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_parameters: Option<TypeParamDeclOrNoop>,
}
@ -524,15 +518,15 @@ pub struct ClassExpression {
#[serde(default)]
pub super_class: Option<Box<Expression>>,
pub body: ClassBody,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub decorators: Option<Vec<Decorator>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub implements: Option<Vec<ClassImpl>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub mixins: Option<InterfaceExtends>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub super_type_parameters: Option<SuperTypeParams>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_parameters: Option<TypeParamDeclOrNoop>,
}

View File

@ -0,0 +1,88 @@
use crate::Loc;
use scoped_tls::scoped_thread_local;
scoped_thread_local!(static FLAVOR: Flavor);
#[repr(u8)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Flavor {
Babel,
Acorn,
}
impl Default for Flavor {
fn default() -> Self {
Flavor::Babel
}
}
impl Flavor {
pub fn with<F, Ret>(self, op: F) -> Ret
where
F: FnOnce() -> Ret,
{
FLAVOR.set(&self, || op())
}
pub fn current() -> Self {
if FLAVOR.is_set() {
FLAVOR.with(|v| *v)
} else {
Flavor::default()
}
}
pub fn emit_loc(&self) -> bool {
matches!(Self::current(), Flavor::Babel)
}
pub(crate) fn skip_range(_: &Option<[usize; 2]>) -> bool {
matches!(Self::current(), Flavor::Babel)
}
pub(crate) fn skip_loc(_: &Option<Loc>) -> bool {
!Self::current().emit_loc()
}
pub(crate) fn skip_empty<T>(v: &T) -> bool
where
T: IsEmpty,
{
matches!(Self::current(), Flavor::Acorn) && v.is_empty()
}
pub(crate) fn skip_none<T>(v: &Option<T>) -> bool {
matches!(Self::current(), Flavor::Acorn) && v.is_none()
}
pub(crate) fn skip_none_and_false(v: &Option<bool>) -> bool {
matches!(Self::current(), Flavor::Acorn) && matches!(v, None | Some(false))
}
}
pub(crate) trait IsEmpty {
fn is_empty(&self) -> bool;
}
impl IsEmpty for String {
fn is_empty(&self) -> bool {
self.is_empty()
}
}
impl<T> IsEmpty for Vec<T> {
fn is_empty(&self) -> bool {
self.is_empty()
}
}
impl<T> IsEmpty for Option<T>
where
T: IsEmpty,
{
fn is_empty(&self) -> bool {
match self {
Some(v) => v.is_empty(),
None => true,
}
}
}

View File

@ -679,14 +679,14 @@ pub struct DeclareClass {
#[serde(flatten)]
pub base: BaseNode,
pub id: Identifier,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_parameters: Option<TypeParameterInstantiation>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub extends: Option<Vec<InterfaceExtends>>,
pub body: ObjectTypeAnnotation,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub implements: Option<Vec<ClassImplements>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub mixins: Option<Vec<InterfaceExtends>>,
}
@ -714,7 +714,7 @@ pub struct DeclareInterface {
pub body: ObjectTypeAnnotation,
#[serde(default)]
pub implements: Option<Vec<ClassImplements>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub mixins: Option<Vec<InterfaceExtends>>,
}
@ -830,7 +830,7 @@ pub struct InterfaceDeclaration {
pub body: ObjectTypeAnnotation,
#[serde(default)]
pub implements: Option<Vec<ClassImplements>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub mixins: Option<Vec<InterfaceExtends>>,
}

View File

@ -17,11 +17,13 @@ mod comment;
mod common;
mod decl;
mod expr;
pub mod flavor;
mod flow;
mod jsx;
mod lit;
mod module;
mod object;
mod pat;
mod ser;
mod stmt;
mod typescript;

View File

@ -1,11 +1,139 @@
use crate::{common::BaseNode, expr::Expression, typescript::TSType};
use serde::{Deserialize, Serialize};
use crate::{common::BaseNode, expr::Expression, flavor::Flavor, typescript::TSType};
use serde::{ser::SerializeMap, Deserialize, Serialize};
use std::borrow::Cow;
use swc_atoms::JsWord;
use swc_common::ast_serde;
#[derive(Debug, Clone, PartialEq)]
#[ast_serde]
pub enum Literal {
String(StringLiteral),
Numeric(NumericLiteral),
Null(NullLiteral),
Boolean(BooleanLiteral),
RegExp(RegExpLiteral),
Template(TemplateLiteral),
BigInt(BigIntLiteral),
Decimal(DecimalLiteral),
}
#[derive(Serialize)]
struct AcornRegex<'a> {
flags: &'a str,
pattern: &'a str,
}
#[derive(Serialize)]
struct Empty {}
impl Serialize for Literal {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match Flavor::current() {
Flavor::Babel => {
let b = match self {
Literal::String(l) => BabelLiteral::String(l.clone()),
Literal::Numeric(l) => BabelLiteral::Numeric(l.clone()),
Literal::Null(l) => BabelLiteral::Null(l.clone()),
Literal::Boolean(l) => BabelLiteral::Boolean(l.clone()),
Literal::RegExp(l) => BabelLiteral::RegExp(l.clone()),
Literal::Template(l) => BabelLiteral::Template(l.clone()),
Literal::BigInt(l) => BabelLiteral::BigInt(l.clone()),
Literal::Decimal(l) => BabelLiteral::Decimal(l.clone()),
};
BabelLiteral::serialize(&b, serializer)
}
Flavor::Acorn => {
let (base, value, raw) = match self {
Literal::String(l) => (
&l.base,
AcornLiteralValue::String(l.value.clone()),
Cow::Borrowed(&*l.value),
),
Literal::Numeric(l) => (
&l.base,
AcornLiteralValue::Numeric(l.value.clone()),
Cow::Owned(l.value.to_string()),
),
Literal::Null(l) => (
&l.base,
AcornLiteralValue::Null(None),
Cow::Borrowed("null"),
),
Literal::Boolean(l) => (
&l.base,
AcornLiteralValue::Boolean(l.value.clone()),
if l.value {
Cow::Borrowed("true")
} else {
Cow::Borrowed("false")
},
),
Literal::RegExp(l) => {
let mut s = serializer.serialize_map(None)?;
{
// TODO(kdy1): This is bad.
l.base
.serialize(serde::__private::ser::FlatMapSerializer(&mut s))?;
}
s.serialize_entry("type", "Literal")?;
s.serialize_entry(
"regex",
&AcornRegex {
flags: &l.flags,
pattern: &l.pattern,
},
)?;
s.serialize_entry("value", &Empty {})?;
return s.end();
}
Literal::Template(..) => todo!(),
Literal::BigInt(l) => (
&l.base,
AcornLiteralValue::BigInt(l.value.clone()),
Cow::Owned(l.value.to_string()),
),
Literal::Decimal(l) => (
&l.base,
AcornLiteralValue::Decimal(l.value.clone()),
Cow::Owned(l.value.to_string()),
),
};
let acorn = AcornLiteral {
type_: "Literal",
raw: &raw,
base,
value,
};
AcornLiteral::serialize(&acorn, serializer)
}
}
}
}
impl<'de> Deserialize<'de> for Literal {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
BabelLiteral::deserialize(deserializer).map(|b| match b {
BabelLiteral::String(l) => Literal::String(l),
BabelLiteral::Numeric(l) => Literal::Numeric(l),
BabelLiteral::Null(l) => Literal::Null(l),
BabelLiteral::Boolean(l) => Literal::Boolean(l),
BabelLiteral::RegExp(l) => Literal::RegExp(l),
BabelLiteral::Template(l) => Literal::Template(l),
BabelLiteral::BigInt(l) => Literal::BigInt(l),
BabelLiteral::Decimal(l) => Literal::Decimal(l),
})
}
}
/// Used for serialization/deserialization
#[ast_serde]
enum BabelLiteral {
#[tag("StringLiteral")]
String(StringLiteral),
#[tag("NumericLiteral")]
@ -24,6 +152,28 @@ pub enum Literal {
Decimal(DecimalLiteral),
}
#[derive(Serialize)]
struct AcornLiteral<'a> {
/// `Literal`.
#[serde(rename = "type")]
type_: &'a str,
raw: &'a str,
#[serde(flatten)]
base: &'a BaseNode,
value: AcornLiteralValue,
}
#[derive(Serialize)]
#[serde(untagged)]
enum AcornLiteralValue {
String(JsWord),
Numeric(f64),
Null(Option<()>),
Boolean(bool),
BigInt(String),
Decimal(JsWord),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type")]
pub struct StringLiteral {

View File

@ -89,12 +89,12 @@ pub struct Program {
#[serde(flatten)]
pub base: BaseNode,
pub body: Vec<Statement>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub directives: Vec<Directive>,
pub source_type: SrcType,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::ser::skip_interpreter")]
pub interpreter: Option<InterpreterDirective>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub source_file: String,
}

View File

@ -1,4 +1,4 @@
use serde::{Deserialize, Serialize};
use serde::{ser::SerializeMap, Deserialize, Serialize};
use swc_common::ast_serde;
use crate::{
@ -6,6 +6,7 @@ use crate::{
BaseNode, Decorator, Identifier, Param, PatternLike, TypeAnnotOrNoop, TypeParamDeclOrNoop,
},
expr::Expression,
flavor::Flavor,
flow::{
ObjectTypeCallProperty, ObjectTypeIndexer, ObjectTypeInternalSlot, ObjectTypeProperty,
ObjectTypeSpreadProperty,
@ -101,8 +102,7 @@ pub enum ObjectPropVal {
Expr(Box<Expression>),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type")]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct ObjectProperty {
#[serde(flatten)]
pub base: BaseNode,
@ -112,6 +112,69 @@ pub struct ObjectProperty {
pub computed: bool,
#[serde(default)]
pub shorthand: bool,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub decorators: Option<Vec<Decorator>>,
}
#[derive(Serialize)]
struct BabelObjectProperty<'a> {
#[serde(rename = "type")]
type_: &'a str,
#[serde(flatten)]
base: &'a BaseNode,
key: &'a ObjectKey,
value: &'a ObjectPropVal,
method: bool,
computed: bool,
shorthand: bool,
#[serde(skip_serializing_if = "crate::flavor::Flavor::skip_none")]
decorators: Option<&'a [Decorator]>,
}
impl Serialize for ObjectProperty {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match Flavor::current() {
Flavor::Babel => {
let actual = BabelObjectProperty {
type_: "ObjectProperty",
base: &self.base,
key: &self.key,
value: &self.value,
method: false,
computed: self.computed,
shorthand: self.shorthand,
decorators: self.decorators.as_deref(),
};
actual.serialize(serializer)
}
Flavor::Acorn => {
let mut s = serializer.serialize_map(None)?;
{
// TODO(kdy1): This is bad.
self.base
.serialize(serde::__private::ser::FlatMapSerializer(&mut s))?;
}
s.serialize_entry("type", "Property")?;
s.serialize_entry("kind", "init")?;
s.serialize_entry("method", &false)?;
s.serialize_entry("shorthand", &self.shorthand)?;
s.serialize_entry("key", &self.key)?;
s.serialize_entry("value", &self.value)?;
s.serialize_entry("computed", &self.computed)?;
if let Some(decorators) = &self.decorators {
if !decorators.is_empty() {
s.serialize_entry("decorators", decorators)?;
}
}
s.serialize_entry("computed", &self.computed)?;
s.end()
}
}
}
}

View File

@ -35,9 +35,9 @@ pub struct ObjectPattern {
pub base: BaseNode,
#[serde(default)]
pub properties: Vec<ObjectPatternProp>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub decorators: Option<Vec<Decorator>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_annotation: Option<Box<TypeAnnotOrNoop>>,
}
@ -55,27 +55,27 @@ pub enum AssignmentPatternLeft {
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type")]
#[serde(tag = "type", rename_all = "camelCase")]
pub struct AssignmentPattern {
#[serde(flatten)]
pub base: BaseNode,
pub left: AssignmentPatternLeft,
pub right: Box<Expression>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub decorators: Option<Vec<Decorator>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_annotation: Option<Box<TypeAnnotOrNoop>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type")]
#[serde(tag = "type", rename_all = "camelCase")]
pub struct ArrayPattern {
#[serde(flatten)]
pub base: BaseNode,
#[serde(default)]
pub elements: Vec<Option<PatternLike>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub decorators: Option<Vec<Decorator>>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
pub type_annotation: Option<Box<TypeAnnotOrNoop>>,
}

View File

@ -0,0 +1,38 @@
use crate::flavor::Flavor;
use serde::Serializer;
pub(crate) fn serialize_optional<S>(o: &Option<bool>, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
return s.serialize_some(&o.unwrap_or(false));
}
/// Always serializes as a boolean value.
pub(crate) fn serialize_as_bool<S>(o: &Option<bool>, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
s.serialize_bool(o.unwrap_or(false))
}
pub(crate) fn skip_expression_for_fn<T>(_: T) -> bool {
match Flavor::current() {
Flavor::Acorn => false,
Flavor::Babel => true,
}
}
pub(crate) fn skip_interpreter<T>(_: T) -> bool {
match Flavor::current() {
Flavor::Acorn => true,
Flavor::Babel => false,
}
}
pub(crate) fn skip_typescript<T>(_: T) -> bool {
match Flavor::current() {
Flavor::Acorn => true,
Flavor::Babel => false,
}
}

View File

@ -185,7 +185,7 @@ pub struct BlockStatement {
pub base: BaseNode,
#[serde(default)]
pub body: Vec<Statement>,
#[serde(default)]
#[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
pub directives: Vec<Directive>,
}

View File

@ -6,21 +6,11 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_estree_compat"
repository = "https://github.com/swc-project/swc.git"
version = "0.2.1"
version = "0.3.0"
[package.metadata.docs.rs]
all-features = true
[features]
flavor-acorn = [
"swc_estree_ast/flavor-acorn",
"swc_estree_visit/flavor-acorn",
]
flavor-babel = [
"swc_estree_ast/flavor-babel",
"swc_estree_visit/flavor-babel",
]
[dependencies]
ahash = {version = "0.7.0", features = ["compile-time-rng"]}
anyhow = "1"
@ -34,14 +24,15 @@ swc_ecma_ast = {version = "0.58", path = "../swc_ecma_ast"}
swc_ecma_parser = {version = "0.78", path = "../swc_ecma_parser"}
swc_ecma_utils = {version = "0.52.3", path = "../swc_ecma_utils"}
swc_ecma_visit = {version = "0.44", path = "../swc_ecma_visit"}
swc_estree_ast = {version = "0.1", path = "../swc_estree_ast"}
swc_estree_macros = {version = "0.1", path = "../swc_estree_macros/"}
swc_estree_visit = {version = "0.1", path = "../swc_estree_visit"}
swc_estree_ast = {version = "0.2.0", path = "../swc_estree_ast"}
swc_node_comments = {version = "0.1", path = "../swc_node_comments/"}
[dev-dependencies]
pretty_assertions = "0.7.1"
swc = {version = "0.87.1", path = "../swc"}
swc_ecma_ast = {version = "0.58.0", path = "../swc_ecma_ast"}
swc_ecma_parser = {version = "0.78.7", path = "../swc_ecma_parser"}
swc_ecma_transforms = {version = "0.95.1", path = "../swc_ecma_transforms/"}
swc_node_base = {version = "0.5", path = "../swc_node_base"}
testing = {version = "0.15.1", path = "../testing"}
walkdir = "2"

View File

@ -0,0 +1,10 @@
// File to parse input as an AST using acorn
const acorn = require("acorn");
const res = acorn.parse(process.argv[1], {
ecmaVersion: 2020,
ranges: true,
allowHashBang: true
})
console.log(JSON.stringify(res, void 0, 2));

View File

@ -35,6 +35,7 @@ impl Babelify for FnDecl {
body: func.body,
generator: func.generator,
is_async: func.is_async,
expression: false,
return_type: func.return_type,
type_parameters: func.type_parameters,
}

View File

@ -9,14 +9,15 @@ use swc_ecma_ast::{
TaggedTpl, ThisExpr, Tpl, TplElement, UnaryExpr, UpdateExpr, YieldExpr,
};
use swc_estree_ast::{
ArrayExprEl, ArrayExpression, ArrowFuncExprBody, ArrowFunctionExpression, AssignmentExpression,
AwaitExpression, BinaryExprLeft, BinaryExpression, CallExpression, Callee, ClassExpression,
ConditionalExpression, Expression, FunctionExpression, LVal, LogicalExpression, MemberExprProp,
MemberExpression, MetaProperty, NewExpression, ObjectExprProp, ObjectExpression, ObjectKey,
ObjectMember, ParenthesizedExpression, PrivateName, SequenceExpression,
SpreadElement as BabelSpreadElement, Super as BabelSuper, TaggedTemplateExprTypeParams,
TaggedTemplateExpression, TemplateElVal, TemplateElement, TemplateLiteral, TemplateLiteralExpr,
ThisExpression, UnaryExpression, UpdateExpression, YieldExpression,
flavor::Flavor, ArrayExprEl, ArrayExpression, ArrowFuncExprBody, ArrowFunctionExpression,
AssignmentExpression, AwaitExpression, BinaryExprLeft, BinaryExpression, CallExpression,
Callee, ClassExpression, ConditionalExpression, Expression, FunctionExpression, LVal, Literal,
LogicalExpression, MemberExprProp, MemberExpression, MetaProperty, NewExpression,
ObjectExprProp, ObjectExpression, ObjectKey, ObjectMember, ParenthesizedExpression,
PrivateName, SequenceExpression, SpreadElement as BabelSpreadElement, Super as BabelSuper,
TaggedTemplateExprTypeParams, TaggedTemplateExpression, TemplateElVal, TemplateElement,
TemplateLiteral, TemplateLiteralExpr, ThisExpression, UnaryExpression, UpdateExpression,
YieldExpression,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -70,22 +71,22 @@ impl Babelify for Expr {
Expr::Lit(lit) => {
match lit {
Lit::Str(s) => ExprOutput::Expr(
Box::alloc().init(Expression::StringLiteral(s.babelify(ctx))),
Box::alloc().init(Expression::Literal(Literal::String(s.babelify(ctx)))),
),
Lit::Bool(b) => ExprOutput::Expr(
Box::alloc().init(Expression::BooleanLiteral(b.babelify(ctx))),
Box::alloc().init(Expression::Literal(Literal::Boolean(b.babelify(ctx)))),
),
Lit::Null(n) => ExprOutput::Expr(
Box::alloc().init(Expression::NullLiteral(n.babelify(ctx))),
Box::alloc().init(Expression::Literal(Literal::Null(n.babelify(ctx)))),
),
Lit::Num(n) => ExprOutput::Expr(
Box::alloc().init(Expression::NumericLiteral(n.babelify(ctx))),
Box::alloc().init(Expression::Literal(Literal::Numeric(n.babelify(ctx)))),
),
Lit::BigInt(i) => ExprOutput::Expr(
Box::alloc().init(Expression::BigIntLiteral(i.babelify(ctx))),
Box::alloc().init(Expression::Literal(Literal::BigInt(i.babelify(ctx)))),
),
Lit::Regex(r) => ExprOutput::Expr(
Box::alloc().init(Expression::RegExpLiteral(r.babelify(ctx))),
Box::alloc().init(Expression::Literal(Literal::RegExp(r.babelify(ctx)))),
),
Lit::JSXText(_) => panic!(
"illegal conversion: Cannot convert {:?} to ExprOutput",
@ -187,8 +188,8 @@ impl From<ExprOutput> for ObjectKey {
match o {
ExprOutput::Expr(e) => match *e {
Expression::Id(i) => ObjectKey::Id(i),
Expression::StringLiteral(s) => ObjectKey::String(s),
Expression::NumericLiteral(n) => ObjectKey::Numeric(n),
Expression::Literal(Literal::String(s)) => ObjectKey::String(s),
Expression::Literal(Literal::Numeric(n)) => ObjectKey::Numeric(n),
_ => ObjectKey::Expr(e),
},
ExprOutput::Private(_) => panic!(
@ -463,12 +464,15 @@ impl Babelify for ArrowExpr {
.collect(),
body: Box::alloc().init(self.body.babelify(ctx)),
is_async: self.is_async,
expression: match Flavor::current() {
Flavor::Babel => Default::default(),
Flavor::Acorn => true,
},
generator: self.is_generator,
expression: Default::default(),
type_parameters: self.type_params.map(|t| t.babelify(ctx).into()),
return_type: self
.return_type
.map(|t| Box::alloc().init(t.babelify(ctx).into())),
type_parameters: self.type_params.map(|t| t.babelify(ctx).into()),
}
}
}

View File

@ -8,7 +8,7 @@ use swc_ecma_ast::{
JSXOpeningFragment, JSXSpreadChild, JSXText, Lit,
};
use swc_estree_ast::{
JSXAttrName as BabelJSXAttrName, JSXAttrVal, JSXAttribute,
flavor::Flavor, JSXAttrName as BabelJSXAttrName, JSXAttrVal, JSXAttribute,
JSXClosingElement as BabelJSXClosingElement, JSXClosingFragment as BabelJSXClosingFragment,
JSXElement as BabelJSXElement, JSXElementChild as BabelJSXElementChild,
JSXElementName as BabelJSXElementName, JSXEmptyExpression, JSXExprContainerExpr,
@ -244,13 +244,16 @@ impl Babelify for JSXElement {
type Output = BabelJSXElement;
fn babelify(self, ctx: &Context) -> Self::Output {
let self_closing = self.closing != None;
let self_closing = match Flavor::current() {
Flavor::Babel => None,
Flavor::Acorn => Some(self.closing.is_some()),
};
BabelJSXElement {
base: ctx.base(self.span),
opening_element: self.opening.babelify(ctx),
closing_element: self.closing.map(|el| el.babelify(ctx)),
children: self.children.babelify(ctx),
self_closing: Some(self_closing),
self_closing,
}
}
}

View File

@ -7,7 +7,7 @@ use swc_common::{
BytePos, SourceFile, SourceMap, Span,
};
use swc_ecma_ast::Class;
use swc_estree_ast::{BaseComment, BaseNode, Comment, LineCol, Loc};
use swc_estree_ast::{flavor::Flavor, BaseComment, BaseNode, Comment, CommentType, LineCol, Loc};
use swc_node_comments::SwcComments;
mod class;
@ -19,7 +19,6 @@ mod jsx;
mod lit;
mod module;
mod module_decl;
pub mod normalize;
mod operators;
mod pat;
mod prop;
@ -62,6 +61,9 @@ impl Context {
if span.is_dummy() {
return None;
}
if !Flavor::current().emit_loc() {
return None;
}
let start = self.line_col(span.lo)?;
let end = self.line_col(span.hi)?;
@ -77,6 +79,10 @@ impl Context {
let loc = self.loc(c.span).unwrap_or_else(Loc::dummy);
let comment = BaseComment {
type_: match c.kind {
CommentKind::Line => CommentType::Line,
CommentKind::Block => CommentType::Block,
},
value: c.text,
start: start.unwrap_or_default(),
end: end.unwrap_or_default(),
@ -118,8 +124,14 @@ impl Context {
start,
end,
loc,
/* TODO(kdy1): Use this field.
* extra: Default::default(), */
range: if matches!(Flavor::current(), Flavor::Acorn) {
match (start, end) {
(Some(start), Some(end)) => Some([start, end]),
_ => None,
}
} else {
None
},
}
}
}

View File

@ -4,8 +4,8 @@ use swc_common::{comments::Comment, Span};
use swc_ecma_ast::{Invalid, Module, ModuleItem, Program, Script};
use swc_ecma_visit::{Node, Visit, VisitWith};
use swc_estree_ast::{
BaseNode, File, InterpreterDirective, LineCol, Loc, ModuleDeclaration, Program as BabelProgram,
SrcType, Statement,
flavor::Flavor, BaseNode, File, InterpreterDirective, LineCol, Loc, ModuleDeclaration,
Program as BabelProgram, SrcType, Statement,
};
use swc_node_comments::SwcComments;
@ -27,6 +27,14 @@ impl Babelify for Program {
start: program.base.start,
end: program.base.end,
loc: program.base.loc,
range: if matches!(Flavor::current(), Flavor::Acorn) {
match (program.base.start, program.base.end) {
(Some(start), Some(end)) => Some([start, end]),
_ => None,
}
} else {
None
},
},
program,
comments: Some(ctx.convert_comments(comments)),
@ -91,6 +99,10 @@ impl Babelify for Script {
/// Module nodes.
fn base_with_trailing_newline(span: Span, ctx: &Context) -> BaseNode {
let mut base = ctx.base(span);
if matches!(Flavor::current(), Flavor::Acorn) {
return base;
}
base.end = base.end.map(|num| num + 1);
base.loc = base.loc.map(|loc| Loc {
end: LineCol {
@ -99,6 +111,8 @@ fn base_with_trailing_newline(span: Span, ctx: &Context) -> BaseNode {
},
..loc
});
base.range = base.range.map(|range| [range[0], range[1] + 1]);
base
}

View File

@ -1,158 +0,0 @@
use swc_atoms::js_word;
use swc_estree_ast::*;
use swc_estree_visit::{VisitMut, VisitMutWith};
struct Normalizer;
// NOTE: When adding a visitor function, don't forget to add
// ```
// node.visit_mut_children_with(self);
// ```
// at the end! Failing to do so breaks the walk chain and other functions never
// get called.
impl VisitMut for Normalizer {
// ------------------------------------------------------------------------
// class
fn visit_mut_class_declaration(&mut self, node: &mut ClassDeclaration) {
if node.decorators == None {
node.decorators = Some(vec![]);
}
if node.is_abstract == None {
node.is_abstract = Some(false);
}
if node.declare == None {
node.declare = Some(false);
}
if node.implements == None {
node.implements = Some(vec![]);
}
node.visit_mut_children_with(self);
}
fn visit_mut_class_method(&mut self, node: &mut ClassMethod) {
if node.computed == None {
node.computed = Some(false);
}
if node.is_static == None {
node.is_static = Some(false);
}
if node.generator == None {
node.generator = Some(false);
}
if node.is_async == None {
node.is_async = Some(false);
}
if node.optional == None {
node.optional = Some(false);
}
if node.is_abstract == None {
node.is_abstract = Some(false);
}
if node.decorators == None {
node.decorators = Some(vec![]);
}
node.visit_mut_children_with(self);
}
fn visit_mut_class_property(&mut self, node: &mut ClassProperty) {
if node.readonly == None {
node.readonly = Some(false);
}
if node.optional == None {
node.optional = Some(false);
}
if node.definite == None {
node.definite = Some(false);
}
if node.declare == None {
node.declare = Some(false);
}
if node.is_abstract == None {
node.is_abstract = Some(false);
}
if node.decorators == None {
node.decorators = Some(vec![]);
}
node.visit_mut_children_with(self);
}
// ------------------------------------------------------------------------
// common
fn visit_mut_rest_element(&mut self, node: &mut RestElement) {
if node.decorators == None {
node.decorators = Some(vec![]);
}
node.visit_mut_children_with(self);
}
// ------------------------------------------------------------------------
// decl
fn visit_mut_variable_declarator(&mut self, node: &mut VariableDeclarator) {
if node.definite == None {
node.definite = Some(false);
}
node.visit_mut_children_with(self);
}
fn visit_mut_variable_declaration(&mut self, node: &mut VariableDeclaration) {
if node.declare == None {
node.declare = Some(false);
}
node.visit_mut_children_with(self);
}
// ------------------------------------------------------------------------
// expr
fn visit_mut_class_expression(&mut self, node: &mut ClassExpression) {
if node.decorators == None {
node.decorators = Some(vec![]);
}
if node.implements == None {
node.implements = Some(vec![]);
}
node.visit_mut_children_with(self);
}
// ------------------------------------------------------------------------
// ident
fn visit_mut_identifier(&mut self, node: &mut Identifier) {
if node.optional == None {
node.optional = Some(false);
}
if node.decorators == None {
node.decorators = Some(vec![]);
}
node.visit_mut_children_with(self);
}
// ------------------------------------------------------------------------
// jsx
fn visit_mut_jsx_element(&mut self, node: &mut JSXElement) {
// From what I can tell, babel just ignores this field, whereas swc sets it,
// causing the trees to diverge. So we just normalize it to always None to
// match babel.
node.self_closing = None;
node.visit_mut_children_with(self);
}
fn visit_mut_jsx_text(&mut self, node: &mut JSXText) {
if node.value.trim().is_empty() {
node.value = js_word!("");
}
node.visit_mut_children_with(self);
}
// ------------------------------------------------------------------------
// pat
fn visit_mut_assignment_pattern(&mut self, node: &mut AssignmentPattern) {
if node.decorators == None {
node.decorators = Some(vec![]);
}
node.visit_mut_children_with(self);
}
}
pub fn normalize(ast: &mut File) {
let mut normalizer = Normalizer {};
ast.visit_mut_with(&mut normalizer);
}

View File

@ -16,9 +16,9 @@ use swc_estree_ast::{
BindExpression, CallExpression, Callee, ClassExpression, ConditionalExpression, DoExpression,
Expression, FunctionExpression, Identifier, Import, JSXAttrVal, JSXAttribute,
JSXEmptyExpression, JSXExprContainerExpr, JSXExpressionContainer, JSXMemberExprObject,
JSXMemberExpression, JSXSpreadAttribute, LogicalExprOp, LogicalExpression, MemberExprProp,
MemberExpression, MetaProperty, ModuleExpression, NewExpression, ObjectExprProp,
ObjectExpression, ObjectKey, ObjectMethod, ObjectPropVal, ObjectProperty,
JSXMemberExpression, JSXSpreadAttribute, Literal, LogicalExprOp, LogicalExpression,
MemberExprProp, MemberExpression, MetaProperty, ModuleExpression, NewExpression,
ObjectExprProp, ObjectExpression, ObjectKey, ObjectMethod, ObjectPropVal, ObjectProperty,
OptionalCallExpression, OptionalMemberExprProp, OptionalMemberExpression,
ParenthesizedExpression, PatternLike, PipelinePrimaryTopicReference, RecordExpression,
SequenceExpression, TSAsExpression, TSNonNullExpression, TSTypeAssertion,
@ -41,11 +41,11 @@ impl Swcify for Expression {
Expression::Conditional(e) => e.swcify(ctx).into(),
Expression::Func(e) => e.swcify(ctx).into(),
Expression::Id(e) => e.swcify(ctx).id.into(),
Expression::StringLiteral(e) => e.swcify(ctx).into(),
Expression::NumericLiteral(e) => e.swcify(ctx).into(),
Expression::NullLiteral(e) => Lit::from(e.swcify(ctx)).into(),
Expression::BooleanLiteral(e) => Lit::from(e.swcify(ctx)).into(),
Expression::RegExpLiteral(e) => Lit::from(e.swcify(ctx)).into(),
Expression::Literal(Literal::String(e)) => e.swcify(ctx).into(),
Expression::Literal(Literal::Numeric(e)) => e.swcify(ctx).into(),
Expression::Literal(Literal::Null(e)) => Lit::from(e.swcify(ctx)).into(),
Expression::Literal(Literal::Boolean(e)) => Lit::from(e.swcify(ctx)).into(),
Expression::Literal(Literal::RegExp(e)) => Lit::from(e.swcify(ctx)).into(),
Expression::Logical(e) => e.swcify(ctx).into(),
Expression::Member(e) => e.swcify(ctx).into(),
Expression::New(e) => e.swcify(ctx).into(),
@ -63,12 +63,12 @@ impl Swcify for Expression {
Expression::TemplateLiteral(e) => e.swcify(ctx).into(),
Expression::Yield(e) => e.swcify(ctx).into(),
Expression::Await(e) => e.swcify(ctx).into(),
Expression::BigIntLiteral(e) => Expr::Lit(e.swcify(ctx).into()),
Expression::Literal(Literal::BigInt(e)) => Expr::Lit(e.swcify(ctx).into()),
Expression::OptionalMember(e) => e.swcify(ctx).into(),
Expression::OptionalCall(e) => e.swcify(ctx).into(),
Expression::JSXElement(e) => Box::new(e.swcify(ctx)).into(),
Expression::JSXFragment(e) => e.swcify(ctx).into(),
Expression::DecimalLiteral(e) => e.swcify(ctx).into(),
Expression::Literal(Literal::Decimal(e)) => e.swcify(ctx).into(),
Expression::TSAs(e) => e.swcify(ctx).into(),
Expression::TSTypeAssertion(e) => e.swcify(ctx).into(),
Expression::TSNonNull(e) => e.swcify(ctx).into(),

View File

@ -4,6 +4,7 @@ extern crate test;
use anyhow::{Context as AnyhowContext, Error};
use copyless::BoxHelper;
use pretty_assertions::assert_eq;
use serde_json::{Number, Value};
use std::{
env, fs,
path::{Path, PathBuf},
@ -15,9 +16,9 @@ use swc_common::{
FileName, FilePathMapping, SourceMap,
};
use swc_ecma_parser::{EsConfig, Syntax};
use swc_estree_ast::File;
use swc_estree_compat::babelify::{normalize::normalize, Babelify, Context};
use swc_estree_compat::babelify::{Babelify, Context};
use test::{test_main, DynTestFn, ShouldPanic, TestDesc, TestDescAndFn, TestName, TestType};
use testing::{json::diff_json_value, DebugUsingDisplay};
use walkdir::WalkDir;
#[test]
@ -146,59 +147,88 @@ fn run_test(src: String, expected: String, syntax: Syntax, is_module: bool) {
cm,
comments: compiler.comments().clone(),
};
let mut ast = swc_ast.babelify(&ctx);
normalize(&mut ast);
println!("Actual: {:?}", ast);
let ast = swc_ast.babelify(&ctx);
let mut expected_ast: File = serde_json::from_str(&expected).unwrap();
normalize(&mut expected_ast);
let mut actual = serde_json::to_value(&ast).unwrap();
assert_eq!(expected_ast, ast);
println!(
"Actual: \n{}",
serde_json::to_string_pretty(&actual).unwrap()
);
let mut expected: Value = serde_json::from_str(&expected).unwrap();
diff_json_value(&mut actual, &mut expected, &mut |k, v| match k {
"identifierName" | "extra" | "errors" => {
// Remove
*v = Value::Null;
}
"optional" | "computed" | "static" | "abstract" | "declare" | "definite" | "generator"
| "readonly" | "expression" => {
// TODO(kdy1): Remove this
match v {
Value::Bool(false) => {
*v = Value::Null;
}
_ => {}
}
}
"decorators" | "implements" => {
// TODO(kdy1): Remove this
match v {
Value::Array(arr) => {
if arr.is_empty() {
*v = Value::Null;
}
}
_ => {}
}
}
"sourceFile" => {
// TODO(kdy1): Remove this
match v {
Value::String(s) => {
if s.is_empty() {
*v = Value::Null;
}
}
_ => {}
}
}
"value" => {
// Normalize numbers
match v {
Value::Number(n) => {
*n = Number::from_f64(n.as_f64().unwrap()).unwrap();
}
Value::String(s) => {
// TODO(kdy1): Remove this
// This is wrong, but we are not babel ast at the moment
*s = s.replace("\n", "");
}
_ => {}
}
}
_ => {}
});
let actual = serde_json::to_string_pretty(&actual).unwrap();
let expected = serde_json::to_string_pretty(&expected).unwrap();
assert_eq!(DebugUsingDisplay(&actual), DebugUsingDisplay(&expected));
}
fn get_test_name(path: &Path, fixture_path: &Path) -> Result<String, Error> {
let s: String = path.strip_prefix(fixture_path)?.to_string_lossy().into();
Ok(s)
}
/*
#[test]
pub fn t1() -> Result<()> {
// let src = fs::read_to_string("x.js")?;
let src = fs::read_to_string("tests/fixture/simple/input.js")?;
let cm = Arc::new(SourceMap::new(FilePathMapping::empty()));
let handler = Arc::new(Handler::with_tty_emitter(
ColorConfig::Always,
true,
false,
Some(cm.clone()),
));
let compiler = Compiler::new(cm.clone(), handler);
let fm = compiler.cm.new_source_file(FileName::Anon, src);
let swc_ast = compiler.parse_js(
fm.clone(),
Default::default(),
Default::default(),
false,
true, // parse conmments
)?;
let ctx = Context {
fm: fm,
cm: cm,
comments: Arc::new(compiler.comments().clone()),
};
let ast = swc_ast.babelify(&ctx);
// let output = fs::read_to_string("x.json")?;
let output = fs::read_to_string("tests/fixture/simple/output.json")?;
let expected_ast: File = serde_json::from_str(&output)?;
assert_eq!(expected_ast, ast);
// println!("FROM SWC\n\n{:#?}\n\nFROM BABEL\n\n{:#?}", ast, expected_ast);
Ok(())
}
*/

View File

@ -0,0 +1,152 @@
use anyhow::Context;
use serde_json::{Number, Value};
use std::{
path::{Path, PathBuf},
process::{Command, Stdio},
};
use swc::SwcComments;
use swc_ecma_ast::EsVersion;
use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, StringInput, Syntax};
use swc_estree_ast::flavor::Flavor;
use swc_estree_compat::babelify::Babelify;
use testing::{assert_eq, json::diff_json_value, DebugUsingDisplay, NormalizedOutput};
fn assert_flavor(flavor: Flavor, input: &Path, output_json_path: &Path) {
testing::run_test(false, |cm, _handler| {
let fm = cm.load_file(input).unwrap();
let lexer = Lexer::new(
Syntax::Es(EsConfig {
static_blocks: true,
..Default::default()
}),
EsVersion::latest(),
StringInput::from(&*fm),
None,
);
let mut parser = Parser::new_from(lexer);
let program = parser.parse_program().unwrap();
let ctx = swc_estree_compat::babelify::Context {
fm: fm.clone(),
cm: cm.clone(),
comments: SwcComments::default(),
};
let mut actual = flavor.with(|| {
let program = program.babelify(&ctx).program;
serde_json::to_value(&program).unwrap()
});
let actual_str = serde_json::to_string_pretty(&actual).unwrap();
println!("----- swc output -----\n{}", actual_str);
let output = {
let mut cmd = Command::new("node");
cmd.arg("-e")
.arg(include_str!("../scripts/test-acorn.js"))
.arg(&*fm.src)
.stderr(Stdio::inherit());
cmd.output().unwrap()
};
let expected =
String::from_utf8(output.stdout).expect("./acorn.js generated non-utf8 output");
// We don't care about these cases
if expected.trim().is_empty() {
return Ok(());
}
{
let mut expected = serde_json::from_str::<Value>(&expected)
.with_context(|| format!("acorn.js generated invalid json:\n {}", expected))
.unwrap();
println!(
"----- Expected output -----\n{}",
serde_json::to_string_pretty(&expected).unwrap()
);
// We don't try to match fully.
actual["end"] = Value::Null;
expected["end"] = Value::Null;
actual["range"] = Value::Null;
expected["range"] = Value::Null;
diff_json_value(&mut actual, &mut expected, &mut |key, value| {
match &mut *value {
Value::Object(v) => {
if let Some("FunctionExpression") =
v.get("type").and_then(|v| v.as_str()).as_deref()
{
v["range"] = Value::Null;
v["start"] = Value::Null;
v["end"] = Value::Null;
}
}
__ => {}
}
match key {
"expression" => {
// Normalize false to null
match value {
Value::Bool(false) => *value = Value::Null,
_ => {}
}
}
"raw" => {
// Remove `'` and `"` from raw strings.
match value {
Value::String(s) => {
if s.starts_with('\'') && s.ends_with('\'') {
*s = s[1..s.len() - 1].to_string();
} else if s.starts_with('"') && s.ends_with('"') {
*s = s[1..s.len() - 1].to_string();
} else if s.starts_with("/") {
// We don't need raw value of regex at the moment.
*value = Value::Null;
}
}
_ => {}
}
}
"value" => {
// Normalize numbers
match value {
Value::Number(n) => {
*n = Number::from_f64(n.as_f64().unwrap()).unwrap();
}
_ => {}
}
}
_ => {}
}
});
let actual = serde_json::to_string_pretty(&actual).unwrap();
let expected = serde_json::to_string_pretty(&expected).unwrap();
assert_eq!(DebugUsingDisplay(&actual), DebugUsingDisplay(&expected));
}
NormalizedOutput::from(actual_str.clone())
.compare_to_file(&output_json_path)
.unwrap();
Ok(())
})
.unwrap();
}
#[testing::fixture("tests/flavor/acorn/**/input.js")]
fn acorn(input: PathBuf) {
let output = input.parent().unwrap().join("output.json");
assert_flavor(Flavor::Acorn, &input, &output);
}

View File

@ -0,0 +1 @@
const foo = require('acorn');

View File

@ -0,0 +1,76 @@
{
"body": [
{
"declarations": [
{
"end": 28,
"id": {
"end": 9,
"name": "foo",
"range": [
6,
9
],
"start": 6,
"type": "Identifier"
},
"init": {
"arguments": [
{
"end": 27,
"range": [
20,
27
],
"raw": "acorn",
"start": 20,
"type": "Literal",
"value": "acorn"
}
],
"callee": {
"end": 19,
"name": "require",
"range": [
12,
19
],
"start": 12,
"type": "Identifier"
},
"end": 28,
"optional": false,
"range": [
12,
28
],
"start": 12,
"type": "CallExpression"
},
"range": [
6,
28
],
"start": 6,
"type": "VariableDeclarator"
}
],
"end": 29,
"kind": "const",
"range": [
0,
29
],
"start": 0,
"type": "VariableDeclaration"
}
],
"end": 29,
"range": [
0,
29
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,2 @@
const arr = [ 1, 2, 3 ];
const [ a, b, ...other ] = arr;

View File

@ -0,0 +1,168 @@
{
"body": [
{
"declarations": [
{
"end": 23,
"id": {
"end": 9,
"name": "arr",
"range": [
6,
9
],
"start": 6,
"type": "Identifier"
},
"init": {
"elements": [
{
"end": 15,
"range": [
14,
15
],
"raw": "1",
"start": 14,
"type": "Literal",
"value": 1.0
},
{
"end": 18,
"range": [
17,
18
],
"raw": "2",
"start": 17,
"type": "Literal",
"value": 2.0
},
{
"end": 21,
"range": [
20,
21
],
"raw": "3",
"start": 20,
"type": "Literal",
"value": 3.0
}
],
"end": 23,
"range": [
12,
23
],
"start": 12,
"type": "ArrayExpression"
},
"range": [
6,
23
],
"start": 6,
"type": "VariableDeclarator"
}
],
"end": 24,
"kind": "const",
"range": [
0,
24
],
"start": 0,
"type": "VariableDeclaration"
},
{
"declarations": [
{
"end": 55,
"id": {
"elements": [
{
"end": 34,
"name": "a",
"range": [
33,
34
],
"start": 33,
"type": "Identifier"
},
{
"end": 37,
"name": "b",
"range": [
36,
37
],
"start": 36,
"type": "Identifier"
},
{
"argument": {
"end": 47,
"name": "other",
"range": [
42,
47
],
"start": 42,
"type": "Identifier"
},
"end": 47,
"range": [
39,
47
],
"start": 39,
"type": "RestElement"
}
],
"end": 49,
"range": [
31,
49
],
"start": 31,
"type": "ArrayPattern"
},
"init": {
"end": 55,
"name": "arr",
"range": [
52,
55
],
"start": 52,
"type": "Identifier"
},
"range": [
31,
55
],
"start": 31,
"type": "VariableDeclarator"
}
],
"end": 56,
"kind": "const",
"range": [
25,
56
],
"start": 25,
"type": "VariableDeclaration"
}
],
"end": 56,
"range": [
0,
56
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1 @@
const arr = [ 1, 2, 3 ];

View File

@ -0,0 +1,87 @@
{
"body": [
{
"declarations": [
{
"end": 23,
"id": {
"end": 9,
"name": "arr",
"range": [
6,
9
],
"start": 6,
"type": "Identifier"
},
"init": {
"elements": [
{
"end": 15,
"range": [
14,
15
],
"raw": "1",
"start": 14,
"type": "Literal",
"value": 1.0
},
{
"end": 18,
"range": [
17,
18
],
"raw": "2",
"start": 17,
"type": "Literal",
"value": 2.0
},
{
"end": 21,
"range": [
20,
21
],
"raw": "3",
"start": 20,
"type": "Literal",
"value": 3.0
}
],
"end": 23,
"range": [
12,
23
],
"start": 12,
"type": "ArrayExpression"
},
"range": [
6,
23
],
"start": 6,
"type": "VariableDeclarator"
}
],
"end": 24,
"kind": "const",
"range": [
0,
24
],
"start": 0,
"type": "VariableDeclaration"
}
],
"end": 24,
"range": [
0,
24
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,19 @@
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
speak() {
console.log(`${this.name} barks.`);
}
}

View File

@ -0,0 +1,630 @@
{
"body": [
{
"body": {
"body": [
{
"computed": false,
"end": 70,
"key": {
"end": 30,
"name": "constructor",
"range": [
19,
30
],
"start": 19,
"type": "Identifier"
},
"kind": "constructor",
"range": [
19,
70
],
"start": 19,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"end": 64,
"expression": {
"end": 63,
"left": {
"computed": false,
"end": 56,
"object": {
"end": 51,
"range": [
47,
51
],
"start": 47,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 56,
"name": "name",
"range": [
52,
56
],
"start": 52,
"type": "Identifier"
},
"range": [
47,
56
],
"start": 47,
"type": "MemberExpression"
},
"operator": "=",
"range": [
47,
63
],
"right": {
"end": 63,
"name": "name",
"range": [
59,
63
],
"start": 59,
"type": "Identifier"
},
"start": 47,
"type": "AssignmentExpression"
},
"range": [
47,
64
],
"start": 47,
"type": "ExpressionStatement"
}
],
"end": 70,
"range": [
37,
70
],
"start": 37,
"type": "BlockStatement"
},
"end": 70,
"generator": false,
"params": [
{
"end": 35,
"name": "name",
"range": [
31,
35
],
"start": 31,
"type": "Identifier"
}
],
"range": [
37,
70
],
"start": 37,
"type": "FunctionExpression"
}
},
{
"computed": false,
"end": 143,
"key": {
"end": 81,
"name": "speak",
"range": [
76,
81
],
"start": 76,
"type": "Identifier"
},
"kind": "method",
"range": [
76,
143
],
"start": 76,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"end": 137,
"expression": {
"arguments": [
{
"end": 135,
"expressions": [
{
"computed": false,
"end": 118,
"object": {
"end": 113,
"range": [
109,
113
],
"start": 109,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 118,
"name": "name",
"range": [
114,
118
],
"start": 114,
"type": "Identifier"
},
"range": [
109,
118
],
"start": 109,
"type": "MemberExpression"
}
],
"quasis": [
{
"end": 107,
"range": [
107,
107
],
"start": 107,
"tail": false,
"type": "TemplateElement",
"value": {
"cooked": "",
"raw": ""
}
},
{
"end": 134,
"range": [
119,
134
],
"start": 119,
"tail": true,
"type": "TemplateElement",
"value": {
"cooked": " makes a noise.",
"raw": " makes a noise."
}
}
],
"range": [
106,
135
],
"start": 106,
"type": "TemplateLiteral"
}
],
"callee": {
"computed": false,
"end": 105,
"object": {
"end": 101,
"name": "console",
"range": [
94,
101
],
"start": 94,
"type": "Identifier"
},
"optional": false,
"property": {
"end": 105,
"name": "log",
"range": [
102,
105
],
"start": 102,
"type": "Identifier"
},
"range": [
94,
105
],
"start": 94,
"type": "MemberExpression"
},
"end": 136,
"optional": false,
"range": [
94,
136
],
"start": 94,
"type": "CallExpression"
},
"range": [
94,
137
],
"start": 94,
"type": "ExpressionStatement"
}
],
"end": 143,
"range": [
84,
143
],
"start": 84,
"type": "BlockStatement"
},
"end": 143,
"generator": false,
"params": [],
"range": [
84,
143
],
"start": 84,
"type": "FunctionExpression"
}
}
],
"end": 145,
"range": [
13,
145
],
"start": 13,
"type": "ClassBody"
},
"end": 145,
"id": {
"end": 12,
"name": "Animal",
"range": [
6,
12
],
"start": 6,
"type": "Identifier"
},
"range": [
0,
145
],
"start": 0,
"superClass": null,
"type": "ClassDeclaration"
},
{
"body": {
"body": [
{
"computed": false,
"end": 224,
"key": {
"end": 189,
"name": "constructor",
"range": [
178,
189
],
"start": 178,
"type": "Identifier"
},
"kind": "constructor",
"range": [
178,
224
],
"start": 178,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"end": 218,
"expression": {
"arguments": [
{
"end": 216,
"name": "name",
"range": [
212,
216
],
"start": 212,
"type": "Identifier"
}
],
"callee": {
"end": 211,
"range": [
206,
211
],
"start": 206,
"type": "Super"
},
"end": 217,
"optional": false,
"range": [
206,
217
],
"start": 206,
"type": "CallExpression"
},
"range": [
206,
218
],
"start": 206,
"type": "ExpressionStatement"
}
],
"end": 224,
"range": [
196,
224
],
"start": 196,
"type": "BlockStatement"
},
"end": 224,
"generator": false,
"params": [
{
"end": 194,
"name": "name",
"range": [
190,
194
],
"start": 190,
"type": "Identifier"
}
],
"range": [
196,
224
],
"start": 196,
"type": "FunctionExpression"
}
},
{
"computed": false,
"end": 289,
"key": {
"end": 235,
"name": "speak",
"range": [
230,
235
],
"start": 230,
"type": "Identifier"
},
"kind": "method",
"range": [
230,
289
],
"start": 230,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"end": 283,
"expression": {
"arguments": [
{
"end": 281,
"expressions": [
{
"computed": false,
"end": 272,
"object": {
"end": 267,
"range": [
263,
267
],
"start": 263,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 272,
"name": "name",
"range": [
268,
272
],
"start": 268,
"type": "Identifier"
},
"range": [
263,
272
],
"start": 263,
"type": "MemberExpression"
}
],
"quasis": [
{
"end": 261,
"range": [
261,
261
],
"start": 261,
"tail": false,
"type": "TemplateElement",
"value": {
"cooked": "",
"raw": ""
}
},
{
"end": 280,
"range": [
273,
280
],
"start": 273,
"tail": true,
"type": "TemplateElement",
"value": {
"cooked": " barks.",
"raw": " barks."
}
}
],
"range": [
260,
281
],
"start": 260,
"type": "TemplateLiteral"
}
],
"callee": {
"computed": false,
"end": 259,
"object": {
"end": 255,
"name": "console",
"range": [
248,
255
],
"start": 248,
"type": "Identifier"
},
"optional": false,
"property": {
"end": 259,
"name": "log",
"range": [
256,
259
],
"start": 256,
"type": "Identifier"
},
"range": [
248,
259
],
"start": 248,
"type": "MemberExpression"
},
"end": 282,
"optional": false,
"range": [
248,
282
],
"start": 248,
"type": "CallExpression"
},
"range": [
248,
283
],
"start": 248,
"type": "ExpressionStatement"
}
],
"end": 289,
"range": [
238,
289
],
"start": 238,
"type": "BlockStatement"
},
"end": 289,
"generator": false,
"params": [],
"range": [
238,
289
],
"start": 238,
"type": "FunctionExpression"
}
}
],
"end": 291,
"range": [
172,
291
],
"start": 172,
"type": "ClassBody"
},
"end": 291,
"id": {
"end": 156,
"name": "Dog",
"range": [
153,
156
],
"start": 153,
"type": "Identifier"
},
"range": [
147,
291
],
"start": 147,
"superClass": {
"end": 171,
"name": "Animal",
"range": [
165,
171
],
"start": 165,
"type": "Identifier"
},
"type": "ClassDeclaration"
}
],
"end": 291,
"range": [
0,
291
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,22 @@
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
set height(height) { this.height = height; }
set width(width) { this.width = width; }
get area() {
return this.calcArea();
}
calcArea() {
return this.height * this.width;
}
}
const square = new Rectangle(10, 10);
console.log(square.area);

View File

@ -0,0 +1,833 @@
{
"body": [
{
"body": {
"body": [
{
"computed": false,
"end": 114,
"key": {
"end": 33,
"name": "constructor",
"range": [
22,
33
],
"start": 22,
"type": "Identifier"
},
"kind": "constructor",
"range": [
22,
114
],
"start": 22,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"end": 80,
"expression": {
"end": 79,
"left": {
"computed": false,
"end": 70,
"object": {
"end": 63,
"range": [
59,
63
],
"start": 59,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 70,
"name": "height",
"range": [
64,
70
],
"start": 64,
"type": "Identifier"
},
"range": [
59,
70
],
"start": 59,
"type": "MemberExpression"
},
"operator": "=",
"range": [
59,
79
],
"right": {
"end": 79,
"name": "height",
"range": [
73,
79
],
"start": 73,
"type": "Identifier"
},
"start": 59,
"type": "AssignmentExpression"
},
"range": [
59,
80
],
"start": 59,
"type": "ExpressionStatement"
},
{
"end": 108,
"expression": {
"end": 107,
"left": {
"computed": false,
"end": 99,
"object": {
"end": 93,
"range": [
89,
93
],
"start": 89,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 99,
"name": "width",
"range": [
94,
99
],
"start": 94,
"type": "Identifier"
},
"range": [
89,
99
],
"start": 89,
"type": "MemberExpression"
},
"operator": "=",
"range": [
89,
107
],
"right": {
"end": 107,
"name": "width",
"range": [
102,
107
],
"start": 102,
"type": "Identifier"
},
"start": 89,
"type": "AssignmentExpression"
},
"range": [
89,
108
],
"start": 89,
"type": "ExpressionStatement"
}
],
"end": 114,
"range": [
49,
114
],
"start": 49,
"type": "BlockStatement"
},
"end": 114,
"generator": false,
"params": [
{
"end": 40,
"name": "height",
"range": [
34,
40
],
"start": 34,
"type": "Identifier"
},
{
"end": 47,
"name": "width",
"range": [
42,
47
],
"start": 42,
"type": "Identifier"
}
],
"range": [
49,
114
],
"start": 49,
"type": "FunctionExpression"
}
},
{
"computed": false,
"end": 164,
"key": {
"end": 130,
"name": "height",
"range": [
124,
130
],
"start": 124,
"type": "Identifier"
},
"kind": "set",
"range": [
120,
164
],
"start": 120,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"end": 162,
"expression": {
"end": 161,
"left": {
"computed": false,
"end": 152,
"object": {
"end": 145,
"range": [
141,
145
],
"start": 141,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 152,
"name": "height",
"range": [
146,
152
],
"start": 146,
"type": "Identifier"
},
"range": [
141,
152
],
"start": 141,
"type": "MemberExpression"
},
"operator": "=",
"range": [
141,
161
],
"right": {
"end": 161,
"name": "height",
"range": [
155,
161
],
"start": 155,
"type": "Identifier"
},
"start": 141,
"type": "AssignmentExpression"
},
"range": [
141,
162
],
"start": 141,
"type": "ExpressionStatement"
}
],
"end": 164,
"range": [
139,
164
],
"start": 139,
"type": "BlockStatement"
},
"end": 164,
"generator": false,
"params": [
{
"end": 137,
"name": "height",
"range": [
131,
137
],
"start": 131,
"type": "Identifier"
}
],
"range": [
139,
164
],
"start": 139,
"type": "FunctionExpression"
}
},
{
"computed": false,
"end": 210,
"key": {
"end": 179,
"name": "width",
"range": [
174,
179
],
"start": 174,
"type": "Identifier"
},
"kind": "set",
"range": [
170,
210
],
"start": 170,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"end": 208,
"expression": {
"end": 207,
"left": {
"computed": false,
"end": 199,
"object": {
"end": 193,
"range": [
189,
193
],
"start": 189,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 199,
"name": "width",
"range": [
194,
199
],
"start": 194,
"type": "Identifier"
},
"range": [
189,
199
],
"start": 189,
"type": "MemberExpression"
},
"operator": "=",
"range": [
189,
207
],
"right": {
"end": 207,
"name": "width",
"range": [
202,
207
],
"start": 202,
"type": "Identifier"
},
"start": 189,
"type": "AssignmentExpression"
},
"range": [
189,
208
],
"start": 189,
"type": "ExpressionStatement"
}
],
"end": 210,
"range": [
187,
210
],
"start": 187,
"type": "BlockStatement"
},
"end": 210,
"generator": false,
"params": [
{
"end": 185,
"name": "width",
"range": [
180,
185
],
"start": 180,
"type": "Identifier"
}
],
"range": [
187,
210
],
"start": 187,
"type": "FunctionExpression"
}
},
{
"computed": false,
"end": 266,
"key": {
"end": 224,
"name": "area",
"range": [
220,
224
],
"start": 220,
"type": "Identifier"
},
"kind": "get",
"range": [
216,
266
],
"start": 216,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"argument": {
"arguments": [],
"callee": {
"computed": false,
"end": 257,
"object": {
"end": 248,
"range": [
244,
248
],
"start": 244,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 257,
"name": "calcArea",
"range": [
249,
257
],
"start": 249,
"type": "Identifier"
},
"range": [
244,
257
],
"start": 244,
"type": "MemberExpression"
},
"end": 259,
"optional": false,
"range": [
244,
259
],
"start": 244,
"type": "CallExpression"
},
"end": 260,
"range": [
237,
260
],
"start": 237,
"type": "ReturnStatement"
}
],
"end": 266,
"range": [
227,
266
],
"start": 227,
"type": "BlockStatement"
},
"end": 266,
"generator": false,
"params": [],
"range": [
227,
266
],
"start": 227,
"type": "FunctionExpression"
}
},
{
"computed": false,
"end": 331,
"key": {
"end": 280,
"name": "calcArea",
"range": [
272,
280
],
"start": 272,
"type": "Identifier"
},
"kind": "method",
"range": [
272,
331
],
"start": 272,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"argument": {
"end": 324,
"left": {
"computed": false,
"end": 311,
"object": {
"end": 304,
"range": [
300,
304
],
"start": 300,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 311,
"name": "height",
"range": [
305,
311
],
"start": 305,
"type": "Identifier"
},
"range": [
300,
311
],
"start": 300,
"type": "MemberExpression"
},
"operator": "*",
"range": [
300,
324
],
"right": {
"computed": false,
"end": 324,
"object": {
"end": 318,
"range": [
314,
318
],
"start": 314,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 324,
"name": "width",
"range": [
319,
324
],
"start": 319,
"type": "Identifier"
},
"range": [
314,
324
],
"start": 314,
"type": "MemberExpression"
},
"start": 300,
"type": "BinaryExpression"
},
"end": 325,
"range": [
293,
325
],
"start": 293,
"type": "ReturnStatement"
}
],
"end": 331,
"range": [
283,
331
],
"start": 283,
"type": "BlockStatement"
},
"end": 331,
"generator": false,
"params": [],
"range": [
283,
331
],
"start": 283,
"type": "FunctionExpression"
}
}
],
"end": 333,
"range": [
16,
333
],
"start": 16,
"type": "ClassBody"
},
"end": 333,
"id": {
"end": 15,
"name": "Rectangle",
"range": [
6,
15
],
"start": 6,
"type": "Identifier"
},
"range": [
0,
333
],
"start": 0,
"superClass": null,
"type": "ClassDeclaration"
},
{
"declarations": [
{
"end": 371,
"id": {
"end": 347,
"name": "square",
"range": [
341,
347
],
"start": 341,
"type": "Identifier"
},
"init": {
"arguments": [
{
"end": 366,
"range": [
364,
366
],
"raw": "10",
"start": 364,
"type": "Literal",
"value": 10.0
},
{
"end": 370,
"range": [
368,
370
],
"raw": "10",
"start": 368,
"type": "Literal",
"value": 10.0
}
],
"callee": {
"end": 363,
"name": "Rectangle",
"range": [
354,
363
],
"start": 354,
"type": "Identifier"
},
"end": 371,
"range": [
350,
371
],
"start": 350,
"type": "NewExpression"
},
"range": [
341,
371
],
"start": 341,
"type": "VariableDeclarator"
}
],
"end": 372,
"kind": "const",
"range": [
335,
372
],
"start": 335,
"type": "VariableDeclaration"
},
{
"end": 399,
"expression": {
"arguments": [
{
"computed": false,
"end": 397,
"object": {
"end": 392,
"name": "square",
"range": [
386,
392
],
"start": 386,
"type": "Identifier"
},
"optional": false,
"property": {
"end": 397,
"name": "area",
"range": [
393,
397
],
"start": 393,
"type": "Identifier"
},
"range": [
386,
397
],
"start": 386,
"type": "MemberExpression"
}
],
"callee": {
"computed": false,
"end": 385,
"object": {
"end": 381,
"name": "console",
"range": [
374,
381
],
"start": 374,
"type": "Identifier"
},
"optional": false,
"property": {
"end": 385,
"name": "log",
"range": [
382,
385
],
"start": 382,
"type": "Identifier"
},
"range": [
374,
385
],
"start": 374,
"type": "MemberExpression"
},
"end": 398,
"optional": false,
"range": [
374,
398
],
"start": 374,
"type": "CallExpression"
},
"range": [
374,
399
],
"start": 374,
"type": "ExpressionStatement"
}
],
"end": 399,
"range": [
0,
399
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,3 @@
class None {
stub() {}
}

View File

@ -0,0 +1,87 @@
{
"body": [
{
"body": {
"body": [
{
"computed": false,
"end": 26,
"key": {
"end": 21,
"name": "stub",
"range": [
17,
21
],
"start": 17,
"type": "Identifier"
},
"kind": "method",
"range": [
17,
26
],
"start": 17,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [],
"end": 26,
"range": [
24,
26
],
"start": 24,
"type": "BlockStatement"
},
"end": 26,
"generator": false,
"params": [],
"range": [
24,
26
],
"start": 24,
"type": "FunctionExpression"
}
}
],
"end": 28,
"range": [
11,
28
],
"start": 11,
"type": "ClassBody"
},
"end": 28,
"id": {
"end": 10,
"name": "None",
"range": [
6,
10
],
"start": 6,
"type": "Identifier"
},
"range": [
0,
28
],
"start": 0,
"superClass": null,
"type": "ClassDeclaration"
}
],
"end": 28,
"range": [
0,
28
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,8 @@
class Rectangle {
height = 0;
width;
constructor(height, width) {
this.height = height;
this.width = width;
}
}

View File

@ -0,0 +1,7 @@
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
const rect = new Rectangle(2, 3);

View File

@ -0,0 +1,301 @@
{
"body": [
{
"body": {
"body": [
{
"computed": false,
"end": 114,
"key": {
"end": 33,
"name": "constructor",
"range": [
22,
33
],
"start": 22,
"type": "Identifier"
},
"kind": "constructor",
"range": [
22,
114
],
"start": 22,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"end": 80,
"expression": {
"end": 79,
"left": {
"computed": false,
"end": 70,
"object": {
"end": 63,
"range": [
59,
63
],
"start": 59,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 70,
"name": "height",
"range": [
64,
70
],
"start": 64,
"type": "Identifier"
},
"range": [
59,
70
],
"start": 59,
"type": "MemberExpression"
},
"operator": "=",
"range": [
59,
79
],
"right": {
"end": 79,
"name": "height",
"range": [
73,
79
],
"start": 73,
"type": "Identifier"
},
"start": 59,
"type": "AssignmentExpression"
},
"range": [
59,
80
],
"start": 59,
"type": "ExpressionStatement"
},
{
"end": 108,
"expression": {
"end": 107,
"left": {
"computed": false,
"end": 99,
"object": {
"end": 93,
"range": [
89,
93
],
"start": 89,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 99,
"name": "width",
"range": [
94,
99
],
"start": 94,
"type": "Identifier"
},
"range": [
89,
99
],
"start": 89,
"type": "MemberExpression"
},
"operator": "=",
"range": [
89,
107
],
"right": {
"end": 107,
"name": "width",
"range": [
102,
107
],
"start": 102,
"type": "Identifier"
},
"start": 89,
"type": "AssignmentExpression"
},
"range": [
89,
108
],
"start": 89,
"type": "ExpressionStatement"
}
],
"end": 114,
"range": [
49,
114
],
"start": 49,
"type": "BlockStatement"
},
"end": 114,
"generator": false,
"params": [
{
"end": 40,
"name": "height",
"range": [
34,
40
],
"start": 34,
"type": "Identifier"
},
{
"end": 47,
"name": "width",
"range": [
42,
47
],
"start": 42,
"type": "Identifier"
}
],
"range": [
49,
114
],
"start": 49,
"type": "FunctionExpression"
}
}
],
"end": 116,
"range": [
16,
116
],
"start": 16,
"type": "ClassBody"
},
"end": 116,
"id": {
"end": 15,
"name": "Rectangle",
"range": [
6,
15
],
"start": 6,
"type": "Identifier"
},
"range": [
0,
116
],
"start": 0,
"superClass": null,
"type": "ClassDeclaration"
},
{
"declarations": [
{
"end": 149,
"id": {
"end": 127,
"name": "rect",
"range": [
123,
127
],
"start": 123,
"type": "Identifier"
},
"init": {
"arguments": [
{
"end": 145,
"range": [
144,
145
],
"raw": "2",
"start": 144,
"type": "Literal",
"value": 2.0
},
{
"end": 148,
"range": [
147,
148
],
"raw": "3",
"start": 147,
"type": "Literal",
"value": 3.0
}
],
"callee": {
"end": 143,
"name": "Rectangle",
"range": [
134,
143
],
"start": 134,
"type": "Identifier"
},
"end": 149,
"range": [
130,
149
],
"start": 130,
"type": "NewExpression"
},
"range": [
123,
149
],
"start": 123,
"type": "VariableDeclarator"
}
],
"end": 150,
"kind": "const",
"range": [
117,
150
],
"start": 117,
"type": "VariableDeclaration"
}
],
"end": 150,
"range": [
0,
150
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,15 @@
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static displayName = "Point";
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.hypot(dx, dy);
}
}

View File

@ -0,0 +1,6 @@
let Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};

View File

@ -0,0 +1,249 @@
{
"body": [
{
"declarations": [
{
"end": 122,
"id": {
"end": 13,
"name": "Rectangle",
"range": [
4,
13
],
"start": 4,
"type": "Identifier"
},
"init": {
"body": {
"body": [
{
"computed": false,
"end": 120,
"key": {
"end": 39,
"name": "constructor",
"range": [
28,
39
],
"start": 28,
"type": "Identifier"
},
"kind": "constructor",
"range": [
28,
120
],
"start": 28,
"static": false,
"type": "MethodDefinition",
"value": {
"async": false,
"body": {
"body": [
{
"end": 86,
"expression": {
"end": 85,
"left": {
"computed": false,
"end": 76,
"object": {
"end": 69,
"range": [
65,
69
],
"start": 65,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 76,
"name": "height",
"range": [
70,
76
],
"start": 70,
"type": "Identifier"
},
"range": [
65,
76
],
"start": 65,
"type": "MemberExpression"
},
"operator": "=",
"range": [
65,
85
],
"right": {
"end": 85,
"name": "height",
"range": [
79,
85
],
"start": 79,
"type": "Identifier"
},
"start": 65,
"type": "AssignmentExpression"
},
"range": [
65,
86
],
"start": 65,
"type": "ExpressionStatement"
},
{
"end": 114,
"expression": {
"end": 113,
"left": {
"computed": false,
"end": 105,
"object": {
"end": 99,
"range": [
95,
99
],
"start": 95,
"type": "ThisExpression"
},
"optional": false,
"property": {
"end": 105,
"name": "width",
"range": [
100,
105
],
"start": 100,
"type": "Identifier"
},
"range": [
95,
105
],
"start": 95,
"type": "MemberExpression"
},
"operator": "=",
"range": [
95,
113
],
"right": {
"end": 113,
"name": "width",
"range": [
108,
113
],
"start": 108,
"type": "Identifier"
},
"start": 95,
"type": "AssignmentExpression"
},
"range": [
95,
114
],
"start": 95,
"type": "ExpressionStatement"
}
],
"end": 120,
"range": [
55,
120
],
"start": 55,
"type": "BlockStatement"
},
"end": 120,
"generator": false,
"params": [
{
"end": 46,
"name": "height",
"range": [
40,
46
],
"start": 40,
"type": "Identifier"
},
{
"end": 53,
"name": "width",
"range": [
48,
53
],
"start": 48,
"type": "Identifier"
}
],
"range": [
55,
120
],
"start": 55,
"type": "FunctionExpression"
}
}
],
"end": 122,
"range": [
22,
122
],
"start": 22,
"type": "ClassBody"
},
"end": 122,
"id": null,
"range": [
16,
122
],
"start": 16,
"superClass": null,
"type": "ClassExpression"
},
"range": [
4,
122
],
"start": 4,
"type": "VariableDeclarator"
}
],
"end": 123,
"kind": "let",
"range": [
0,
123
],
"start": 0,
"type": "VariableDeclaration"
}
],
"end": 123,
"range": [
0,
123
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,4 @@
/*
A block comment.
*/
let a = false;

View File

@ -0,0 +1,54 @@
{
"body": [
{
"declarations": [
{
"end": 36,
"id": {
"end": 28,
"name": "a",
"range": [
27,
28
],
"start": 27,
"type": "Identifier"
},
"init": {
"end": 36,
"range": [
31,
36
],
"raw": "false",
"start": 31,
"type": "Literal",
"value": false
},
"range": [
27,
36
],
"start": 27,
"type": "VariableDeclarator"
}
],
"end": 37,
"kind": "let",
"range": [
23,
37
],
"start": 23,
"type": "VariableDeclaration"
}
],
"end": 37,
"range": [
0,
37
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,7 @@
function x() {
/*
This is a
block comment.
*/
let a = false;
}

View File

@ -0,0 +1,88 @@
{
"body": [
{
"async": false,
"body": {
"body": [
{
"declarations": [
{
"end": 79,
"id": {
"end": 71,
"name": "a",
"range": [
70,
71
],
"start": 70,
"type": "Identifier"
},
"init": {
"end": 79,
"range": [
74,
79
],
"raw": "false",
"start": 74,
"type": "Literal",
"value": false
},
"range": [
70,
79
],
"start": 70,
"type": "VariableDeclarator"
}
],
"end": 80,
"kind": "let",
"range": [
66,
80
],
"start": 66,
"type": "VariableDeclaration"
}
],
"end": 82,
"range": [
13,
82
],
"start": 13,
"type": "BlockStatement"
},
"end": 82,
"expression": false,
"generator": false,
"id": {
"end": 10,
"name": "x",
"range": [
9,
10
],
"start": 9,
"type": "Identifier"
},
"params": [],
"range": [
0,
82
],
"start": 0,
"type": "FunctionDeclaration"
}
],
"end": 82,
"range": [
0,
82
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,2 @@
// a top level comment
let a = false;

View File

@ -0,0 +1,54 @@
{
"body": [
{
"declarations": [
{
"end": 36,
"id": {
"end": 28,
"name": "a",
"range": [
27,
28
],
"start": 27,
"type": "Identifier"
},
"init": {
"end": 36,
"range": [
31,
36
],
"raw": "false",
"start": 31,
"type": "Literal",
"value": false
},
"range": [
27,
36
],
"start": 27,
"type": "VariableDeclarator"
}
],
"end": 37,
"kind": "let",
"range": [
23,
37
],
"start": 23,
"type": "VariableDeclaration"
}
],
"end": 37,
"range": [
0,
37
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,4 @@
function x() {
// some comment
let a = true; // trailing comment
}

View File

@ -0,0 +1,88 @@
{
"body": [
{
"async": false,
"body": {
"body": [
{
"declarations": [
{
"end": 51,
"id": {
"end": 44,
"name": "a",
"range": [
43,
44
],
"start": 43,
"type": "Identifier"
},
"init": {
"end": 51,
"range": [
47,
51
],
"raw": "true",
"start": 47,
"type": "Literal",
"value": true
},
"range": [
43,
51
],
"start": 43,
"type": "VariableDeclarator"
}
],
"end": 52,
"kind": "let",
"range": [
39,
52
],
"start": 39,
"type": "VariableDeclaration"
}
],
"end": 74,
"range": [
13,
74
],
"start": 13,
"type": "BlockStatement"
},
"end": 74,
"expression": false,
"generator": false,
"id": {
"end": 10,
"name": "x",
"range": [
9,
10
],
"start": 9,
"type": "Identifier"
},
"params": [],
"range": [
0,
74
],
"start": 0,
"type": "FunctionDeclaration"
}
],
"end": 74,
"range": [
0,
74
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,2 @@
let obj = {a: 10};
delete obj.a;

View File

@ -0,0 +1,139 @@
{
"body": [
{
"declarations": [
{
"end": 17,
"id": {
"end": 7,
"name": "obj",
"range": [
4,
7
],
"start": 4,
"type": "Identifier"
},
"init": {
"end": 17,
"properties": [
{
"computed": false,
"end": 16,
"key": {
"end": 12,
"name": "a",
"range": [
11,
12
],
"start": 11,
"type": "Identifier"
},
"kind": "init",
"method": false,
"range": [
11,
16
],
"shorthand": false,
"start": 11,
"type": "Property",
"value": {
"end": 16,
"range": [
14,
16
],
"raw": "10",
"start": 14,
"type": "Literal",
"value": 10.0
}
}
],
"range": [
10,
17
],
"start": 10,
"type": "ObjectExpression"
},
"range": [
4,
17
],
"start": 4,
"type": "VariableDeclarator"
}
],
"end": 18,
"kind": "let",
"range": [
0,
18
],
"start": 0,
"type": "VariableDeclaration"
},
{
"end": 32,
"expression": {
"argument": {
"computed": false,
"end": 31,
"object": {
"end": 29,
"name": "obj",
"range": [
26,
29
],
"start": 26,
"type": "Identifier"
},
"optional": false,
"property": {
"end": 31,
"name": "a",
"range": [
30,
31
],
"start": 30,
"type": "Identifier"
},
"range": [
26,
31
],
"start": 26,
"type": "MemberExpression"
},
"end": 31,
"operator": "delete",
"prefix": true,
"range": [
19,
31
],
"start": 19,
"type": "UnaryExpression"
},
"range": [
19,
32
],
"start": 19,
"type": "ExpressionStatement"
}
],
"end": 32,
"range": [
0,
32
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1 @@
const x = 2 ** 3;

View File

@ -0,0 +1,75 @@
{
"body": [
{
"declarations": [
{
"end": 16,
"id": {
"end": 7,
"name": "x",
"range": [
6,
7
],
"start": 6,
"type": "Identifier"
},
"init": {
"end": 16,
"left": {
"end": 11,
"range": [
10,
11
],
"raw": "2",
"start": 10,
"type": "Literal",
"value": 2.0
},
"operator": "**",
"range": [
10,
16
],
"right": {
"end": 16,
"range": [
15,
16
],
"raw": "3",
"start": 15,
"type": "Literal",
"value": 3.0
},
"start": 10,
"type": "BinaryExpression"
},
"range": [
6,
16
],
"start": 6,
"type": "VariableDeclarator"
}
],
"end": 17,
"kind": "const",
"range": [
0,
17
],
"start": 0,
"type": "VariableDeclaration"
}
],
"end": 17,
"range": [
0,
17
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1 @@
const square = function(number) { return number * number }

View File

@ -0,0 +1,117 @@
{
"body": [
{
"declarations": [
{
"end": 58,
"id": {
"end": 12,
"name": "square",
"range": [
6,
12
],
"start": 6,
"type": "Identifier"
},
"init": {
"async": false,
"body": {
"body": [
{
"argument": {
"end": 56,
"left": {
"end": 47,
"name": "number",
"range": [
41,
47
],
"start": 41,
"type": "Identifier"
},
"operator": "*",
"range": [
41,
56
],
"right": {
"end": 56,
"name": "number",
"range": [
50,
56
],
"start": 50,
"type": "Identifier"
},
"start": 41,
"type": "BinaryExpression"
},
"end": 56,
"range": [
34,
56
],
"start": 34,
"type": "ReturnStatement"
}
],
"end": 58,
"range": [
32,
58
],
"start": 32,
"type": "BlockStatement"
},
"end": 58,
"generator": false,
"id": null,
"params": [
{
"end": 30,
"name": "number",
"range": [
24,
30
],
"start": 24,
"type": "Identifier"
}
],
"range": [
15,
58
],
"start": 15,
"type": "FunctionExpression"
},
"range": [
6,
58
],
"start": 6,
"type": "VariableDeclarator"
}
],
"end": 58,
"kind": "const",
"range": [
0,
58
],
"start": 0,
"type": "VariableDeclaration"
}
],
"end": 58,
"range": [
0,
58
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,7 @@
var a = [
'Hydrogen',
'Helium',
'Lithium',
'Beryllium'
];
var a3 = a.map(s => s.length);

View File

@ -0,0 +1,227 @@
{
"body": [
{
"declarations": [
{
"end": 72,
"id": {
"end": 5,
"name": "a",
"range": [
4,
5
],
"start": 4,
"type": "Identifier"
},
"init": {
"elements": [
{
"end": 24,
"range": [
14,
24
],
"raw": "Hydrogen",
"start": 14,
"type": "Literal",
"value": "Hydrogen"
},
{
"end": 38,
"range": [
30,
38
],
"raw": "Helium",
"start": 30,
"type": "Literal",
"value": "Helium"
},
{
"end": 53,
"range": [
44,
53
],
"raw": "Lithium",
"start": 44,
"type": "Literal",
"value": "Lithium"
},
{
"end": 70,
"range": [
59,
70
],
"raw": "Beryllium",
"start": 59,
"type": "Literal",
"value": "Beryllium"
}
],
"end": 72,
"range": [
8,
72
],
"start": 8,
"type": "ArrayExpression"
},
"range": [
4,
72
],
"start": 4,
"type": "VariableDeclarator"
}
],
"end": 73,
"kind": "var",
"range": [
0,
73
],
"start": 0,
"type": "VariableDeclaration"
},
{
"declarations": [
{
"end": 103,
"id": {
"end": 80,
"name": "a3",
"range": [
78,
80
],
"start": 78,
"type": "Identifier"
},
"init": {
"arguments": [
{
"async": false,
"body": {
"computed": false,
"end": 102,
"object": {
"end": 95,
"name": "s",
"range": [
94,
95
],
"start": 94,
"type": "Identifier"
},
"optional": false,
"property": {
"end": 102,
"name": "length",
"range": [
96,
102
],
"start": 96,
"type": "Identifier"
},
"range": [
94,
102
],
"start": 94,
"type": "MemberExpression"
},
"end": 102,
"expression": true,
"generator": false,
"params": [
{
"end": 90,
"name": "s",
"range": [
89,
90
],
"start": 89,
"type": "Identifier"
}
],
"range": [
89,
102
],
"start": 89,
"type": "ArrowFunctionExpression"
}
],
"callee": {
"computed": false,
"end": 88,
"object": {
"end": 84,
"name": "a",
"range": [
83,
84
],
"start": 83,
"type": "Identifier"
},
"optional": false,
"property": {
"end": 88,
"name": "map",
"range": [
85,
88
],
"start": 85,
"type": "Identifier"
},
"range": [
83,
88
],
"start": 83,
"type": "MemberExpression"
},
"end": 103,
"optional": false,
"range": [
83,
103
],
"start": 83,
"type": "CallExpression"
},
"range": [
78,
103
],
"start": 78,
"type": "VariableDeclarator"
}
],
"end": 104,
"kind": "var",
"range": [
74,
104
],
"start": 74,
"type": "VariableDeclaration"
}
],
"end": 104,
"range": [
0,
104
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,3 @@
function multiply(a, b = 1) {
return a * b;
}

View File

@ -0,0 +1,126 @@
{
"body": [
{
"async": false,
"body": {
"body": [
{
"argument": {
"end": 44,
"left": {
"end": 40,
"name": "a",
"range": [
39,
40
],
"start": 39,
"type": "Identifier"
},
"operator": "*",
"range": [
39,
44
],
"right": {
"end": 44,
"name": "b",
"range": [
43,
44
],
"start": 43,
"type": "Identifier"
},
"start": 39,
"type": "BinaryExpression"
},
"end": 45,
"range": [
32,
45
],
"start": 32,
"type": "ReturnStatement"
}
],
"end": 47,
"range": [
28,
47
],
"start": 28,
"type": "BlockStatement"
},
"end": 47,
"expression": false,
"generator": false,
"id": {
"end": 17,
"name": "multiply",
"range": [
9,
17
],
"start": 9,
"type": "Identifier"
},
"params": [
{
"end": 19,
"name": "a",
"range": [
18,
19
],
"start": 18,
"type": "Identifier"
},
{
"end": 26,
"left": {
"end": 22,
"name": "b",
"range": [
21,
22
],
"start": 21,
"type": "Identifier"
},
"range": [
21,
26
],
"right": {
"end": 26,
"range": [
25,
26
],
"raw": "1",
"start": 25,
"type": "Literal",
"value": 1.0
},
"start": 21,
"type": "AssignmentPattern"
}
],
"range": [
0,
47
],
"start": 0,
"type": "FunctionDeclaration"
}
],
"end": 47,
"range": [
0,
47
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,3 @@
function multiply(multiplier, ...theArgs) {
return theArgs.map(x => multiplier * x);
}

View File

@ -0,0 +1,182 @@
{
"body": [
{
"async": false,
"body": {
"body": [
{
"argument": {
"arguments": [
{
"async": false,
"body": {
"end": 86,
"left": {
"end": 82,
"name": "multiplier",
"range": [
72,
82
],
"start": 72,
"type": "Identifier"
},
"operator": "*",
"range": [
72,
86
],
"right": {
"end": 86,
"name": "x",
"range": [
85,
86
],
"start": 85,
"type": "Identifier"
},
"start": 72,
"type": "BinaryExpression"
},
"end": 86,
"expression": true,
"generator": false,
"params": [
{
"end": 68,
"name": "x",
"range": [
67,
68
],
"start": 67,
"type": "Identifier"
}
],
"range": [
67,
86
],
"start": 67,
"type": "ArrowFunctionExpression"
}
],
"callee": {
"computed": false,
"end": 66,
"object": {
"end": 62,
"name": "theArgs",
"range": [
55,
62
],
"start": 55,
"type": "Identifier"
},
"optional": false,
"property": {
"end": 66,
"name": "map",
"range": [
63,
66
],
"start": 63,
"type": "Identifier"
},
"range": [
55,
66
],
"start": 55,
"type": "MemberExpression"
},
"end": 87,
"optional": false,
"range": [
55,
87
],
"start": 55,
"type": "CallExpression"
},
"end": 88,
"range": [
48,
88
],
"start": 48,
"type": "ReturnStatement"
}
],
"end": 90,
"range": [
42,
90
],
"start": 42,
"type": "BlockStatement"
},
"end": 90,
"expression": false,
"generator": false,
"id": {
"end": 17,
"name": "multiply",
"range": [
9,
17
],
"start": 9,
"type": "Identifier"
},
"params": [
{
"end": 28,
"name": "multiplier",
"range": [
18,
28
],
"start": 18,
"type": "Identifier"
},
{
"argument": {
"end": 40,
"name": "theArgs",
"range": [
33,
40
],
"start": 33,
"type": "Identifier"
},
"end": 40,
"range": [
30,
40
],
"start": 30,
"type": "RestElement"
}
],
"range": [
0,
90
],
"start": 0,
"type": "FunctionDeclaration"
}
],
"end": 90,
"range": [
0,
90
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,3 @@
function square(number) {
return number * number;
}

View File

@ -0,0 +1,96 @@
{
"body": [
{
"async": false,
"body": {
"body": [
{
"argument": {
"end": 50,
"left": {
"end": 41,
"name": "number",
"range": [
35,
41
],
"start": 35,
"type": "Identifier"
},
"operator": "*",
"range": [
35,
50
],
"right": {
"end": 50,
"name": "number",
"range": [
44,
50
],
"start": 44,
"type": "Identifier"
},
"start": 35,
"type": "BinaryExpression"
},
"end": 51,
"range": [
28,
51
],
"start": 28,
"type": "ReturnStatement"
}
],
"end": 53,
"range": [
24,
53
],
"start": 24,
"type": "BlockStatement"
},
"end": 53,
"expression": false,
"generator": false,
"id": {
"end": 15,
"name": "square",
"range": [
9,
15
],
"start": 9,
"type": "Identifier"
},
"params": [
{
"end": 22,
"name": "number",
"range": [
16,
22
],
"start": 16,
"type": "Identifier"
}
],
"range": [
0,
53
],
"start": 0,
"type": "FunctionDeclaration"
}
],
"end": 53,
"range": [
0,
53
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,6 @@
const App = () => {
let t = true;
return <div>
{ t && <span>t</span> }
</div>
};

View File

@ -0,0 +1,5 @@
const App = () => {
return <div>
<div>testing</div>
</div>
};

View File

@ -0,0 +1,6 @@
const App = () => {
let a = [1, 2, 3];
return <ul>
{a.map(item => <li key={item}>{item}</li>)}
</ul>
};

View File

@ -0,0 +1,3 @@
const App = props => {
return <div id="app" { ...props } />
};

View File

@ -0,0 +1,4 @@
const App = () => {
let name = "thing";
return <div id="app" className={ "a " + name } />
};

View File

@ -0,0 +1,3 @@
const App = () => {
return <div />
};

View File

@ -0,0 +1,3 @@
const Component = () => {
return <span>hello</span>
};

View File

@ -0,0 +1,6 @@
const App = () => {
let t = "a";
return <div>
{ t === "a" ? <span>a</span> : <span>b</span> }
</div>
};

View File

@ -0,0 +1,3 @@
const fs = require("fs");
const s = fs.readFileSync("_placeholder");
module.exports = s;

View File

@ -0,0 +1,221 @@
{
"body": [
{
"declarations": [
{
"end": 24,
"id": {
"end": 8,
"name": "fs",
"range": [
6,
8
],
"start": 6,
"type": "Identifier"
},
"init": {
"arguments": [
{
"end": 23,
"range": [
19,
23
],
"raw": "fs",
"start": 19,
"type": "Literal",
"value": "fs"
}
],
"callee": {
"end": 18,
"name": "require",
"range": [
11,
18
],
"start": 11,
"type": "Identifier"
},
"end": 24,
"optional": false,
"range": [
11,
24
],
"start": 11,
"type": "CallExpression"
},
"range": [
6,
24
],
"start": 6,
"type": "VariableDeclarator"
}
],
"end": 25,
"kind": "const",
"range": [
0,
25
],
"start": 0,
"type": "VariableDeclaration"
},
{
"declarations": [
{
"end": 67,
"id": {
"end": 33,
"name": "s",
"range": [
32,
33
],
"start": 32,
"type": "Identifier"
},
"init": {
"arguments": [
{
"end": 66,
"range": [
52,
66
],
"raw": "_placeholder",
"start": 52,
"type": "Literal",
"value": "_placeholder"
}
],
"callee": {
"computed": false,
"end": 51,
"object": {
"end": 38,
"name": "fs",
"range": [
36,
38
],
"start": 36,
"type": "Identifier"
},
"optional": false,
"property": {
"end": 51,
"name": "readFileSync",
"range": [
39,
51
],
"start": 39,
"type": "Identifier"
},
"range": [
36,
51
],
"start": 36,
"type": "MemberExpression"
},
"end": 67,
"optional": false,
"range": [
36,
67
],
"start": 36,
"type": "CallExpression"
},
"range": [
32,
67
],
"start": 32,
"type": "VariableDeclarator"
}
],
"end": 68,
"kind": "const",
"range": [
26,
68
],
"start": 26,
"type": "VariableDeclaration"
},
{
"end": 88,
"expression": {
"end": 87,
"left": {
"computed": false,
"end": 83,
"object": {
"end": 75,
"name": "module",
"range": [
69,
75
],
"start": 69,
"type": "Identifier"
},
"optional": false,
"property": {
"end": 83,
"name": "exports",
"range": [
76,
83
],
"start": 76,
"type": "Identifier"
},
"range": [
69,
83
],
"start": 69,
"type": "MemberExpression"
},
"operator": "=",
"range": [
69,
87
],
"right": {
"end": 87,
"name": "s",
"range": [
86,
87
],
"start": 86,
"type": "Identifier"
},
"start": 69,
"type": "AssignmentExpression"
},
"range": [
69,
88
],
"start": 69,
"type": "ExpressionStatement"
}
],
"end": 88,
"range": [
0,
88
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,2 @@
const a = 1;
export default a;

View File

@ -0,0 +1,3 @@
export const name = "a";
export function functionName() {}
export class ClassName {}

View File

@ -0,0 +1,2 @@
const a = 1;
export { a };

View File

@ -0,0 +1,2 @@
const x = 1;
export { x as y };

View File

@ -0,0 +1 @@
import a from "b";

View File

@ -0,0 +1,4 @@
import a, {
b,
c,
} from "d";

View File

@ -0,0 +1 @@
import { a } from "b";

View File

@ -0,0 +1 @@
import { a as b } from "c";

View File

@ -0,0 +1 @@
import * as name from "module-name";

View File

@ -0,0 +1,6 @@
const obj = {
a: true,
b: false,
c: null,
};
const { a, b, ...other } = obj;

View File

@ -0,0 +1,283 @@
{
"body": [
{
"declarations": [
{
"end": 55,
"id": {
"end": 9,
"name": "obj",
"range": [
6,
9
],
"start": 6,
"type": "Identifier"
},
"init": {
"end": 55,
"properties": [
{
"computed": false,
"end": 25,
"key": {
"end": 19,
"name": "a",
"range": [
18,
19
],
"start": 18,
"type": "Identifier"
},
"kind": "init",
"method": false,
"range": [
18,
25
],
"shorthand": false,
"start": 18,
"type": "Property",
"value": {
"end": 25,
"range": [
21,
25
],
"raw": "true",
"start": 21,
"type": "Literal",
"value": true
}
},
{
"computed": false,
"end": 39,
"key": {
"end": 32,
"name": "b",
"range": [
31,
32
],
"start": 31,
"type": "Identifier"
},
"kind": "init",
"method": false,
"range": [
31,
39
],
"shorthand": false,
"start": 31,
"type": "Property",
"value": {
"end": 39,
"range": [
34,
39
],
"raw": "false",
"start": 34,
"type": "Literal",
"value": false
}
},
{
"computed": false,
"end": 52,
"key": {
"end": 46,
"name": "c",
"range": [
45,
46
],
"start": 45,
"type": "Identifier"
},
"kind": "init",
"method": false,
"range": [
45,
52
],
"shorthand": false,
"start": 45,
"type": "Property",
"value": {
"end": 52,
"range": [
48,
52
],
"raw": "null",
"start": 48,
"type": "Literal",
"value": null
}
}
],
"range": [
12,
55
],
"start": 12,
"type": "ObjectExpression"
},
"range": [
6,
55
],
"start": 6,
"type": "VariableDeclarator"
}
],
"end": 56,
"kind": "const",
"range": [
0,
56
],
"start": 0,
"type": "VariableDeclaration"
},
{
"declarations": [
{
"end": 87,
"id": {
"end": 81,
"properties": [
{
"computed": false,
"end": 66,
"key": {
"end": 66,
"name": "a",
"range": [
65,
66
],
"start": 65,
"type": "Identifier"
},
"kind": "init",
"method": false,
"range": [
65,
66
],
"shorthand": true,
"start": 65,
"type": "Property",
"value": {
"end": 66,
"name": "a",
"range": [
65,
66
],
"start": 65,
"type": "Identifier"
}
},
{
"computed": false,
"end": 69,
"key": {
"end": 69,
"name": "b",
"range": [
68,
69
],
"start": 68,
"type": "Identifier"
},
"kind": "init",
"method": false,
"range": [
68,
69
],
"shorthand": true,
"start": 68,
"type": "Property",
"value": {
"end": 69,
"name": "b",
"range": [
68,
69
],
"start": 68,
"type": "Identifier"
}
},
{
"argument": {
"end": 79,
"name": "other",
"range": [
74,
79
],
"start": 74,
"type": "Identifier"
},
"end": 79,
"range": [
71,
79
],
"start": 71,
"type": "RestElement"
}
],
"range": [
63,
81
],
"start": 63,
"type": "ObjectPattern"
},
"init": {
"end": 87,
"name": "obj",
"range": [
84,
87
],
"start": 84,
"type": "Identifier"
},
"range": [
63,
87
],
"start": 63,
"type": "VariableDeclarator"
}
],
"end": 88,
"kind": "const",
"range": [
57,
88
],
"start": 57,
"type": "VariableDeclaration"
}
],
"end": 88,
"range": [
0,
88
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,4 @@
let obj = {
a: 1,
b: false,
};

View File

@ -0,0 +1,122 @@
{
"body": [
{
"declarations": [
{
"end": 37,
"id": {
"end": 7,
"name": "obj",
"range": [
4,
7
],
"start": 4,
"type": "Identifier"
},
"init": {
"end": 37,
"properties": [
{
"computed": false,
"end": 20,
"key": {
"end": 17,
"name": "a",
"range": [
16,
17
],
"start": 16,
"type": "Identifier"
},
"kind": "init",
"method": false,
"range": [
16,
20
],
"shorthand": false,
"start": 16,
"type": "Property",
"value": {
"end": 20,
"range": [
19,
20
],
"raw": "1",
"start": 19,
"type": "Literal",
"value": 1.0
}
},
{
"computed": false,
"end": 34,
"key": {
"end": 27,
"name": "b",
"range": [
26,
27
],
"start": 26,
"type": "Identifier"
},
"kind": "init",
"method": false,
"range": [
26,
34
],
"shorthand": false,
"start": 26,
"type": "Property",
"value": {
"end": 34,
"range": [
29,
34
],
"raw": "false",
"start": 29,
"type": "Literal",
"value": false
}
}
],
"range": [
10,
37
],
"start": 10,
"type": "ObjectExpression"
},
"range": [
4,
37
],
"start": 4,
"type": "VariableDeclarator"
}
],
"end": 38,
"kind": "let",
"range": [
0,
38
],
"start": 0,
"type": "VariableDeclaration"
}
],
"end": 38,
"range": [
0,
38
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,7 @@
const a = {
name: "a",
};
const b = {
...a,
name: "b",
};

View File

@ -0,0 +1,183 @@
{
"body": [
{
"declarations": [
{
"end": 28,
"id": {
"end": 7,
"name": "a",
"range": [
6,
7
],
"start": 6,
"type": "Identifier"
},
"init": {
"end": 28,
"properties": [
{
"computed": false,
"end": 25,
"key": {
"end": 20,
"name": "name",
"range": [
16,
20
],
"start": 16,
"type": "Identifier"
},
"kind": "init",
"method": false,
"range": [
16,
25
],
"shorthand": false,
"start": 16,
"type": "Property",
"value": {
"end": 25,
"range": [
22,
25
],
"raw": "a",
"start": 22,
"type": "Literal",
"value": "a"
}
}
],
"range": [
10,
28
],
"start": 10,
"type": "ObjectExpression"
},
"range": [
6,
28
],
"start": 6,
"type": "VariableDeclarator"
}
],
"end": 29,
"kind": "const",
"range": [
0,
29
],
"start": 0,
"type": "VariableDeclaration"
},
{
"declarations": [
{
"end": 68,
"id": {
"end": 37,
"name": "b",
"range": [
36,
37
],
"start": 36,
"type": "Identifier"
},
"init": {
"end": 68,
"properties": [
{
"argument": {
"end": 50,
"name": "a",
"range": [
49,
50
],
"start": 49,
"type": "Identifier"
},
"end": 50,
"range": [
46,
50
],
"start": 46,
"type": "SpreadElement"
},
{
"computed": false,
"end": 65,
"key": {
"end": 60,
"name": "name",
"range": [
56,
60
],
"start": 56,
"type": "Identifier"
},
"kind": "init",
"method": false,
"range": [
56,
65
],
"shorthand": false,
"start": 56,
"type": "Property",
"value": {
"end": 65,
"range": [
62,
65
],
"raw": "b",
"start": 62,
"type": "Literal",
"value": "b"
}
}
],
"range": [
40,
68
],
"start": 40,
"type": "ObjectExpression"
},
"range": [
36,
68
],
"start": 36,
"type": "VariableDeclarator"
}
],
"end": 69,
"kind": "const",
"range": [
30,
69
],
"start": 30,
"type": "VariableDeclaration"
}
],
"end": 69,
"range": [
0,
69
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1 @@
let r = /[0-9]+/im;

View File

@ -0,0 +1,57 @@
{
"body": [
{
"declarations": [
{
"end": 18,
"id": {
"end": 5,
"name": "r",
"range": [
4,
5
],
"start": 4,
"type": "Identifier"
},
"init": {
"end": 18,
"range": [
8,
18
],
"regex": {
"flags": "im",
"pattern": "[0-9]+"
},
"start": 8,
"type": "Literal",
"value": {}
},
"range": [
4,
18
],
"start": 4,
"type": "VariableDeclarator"
}
],
"end": 19,
"kind": "let",
"range": [
0,
19
],
"start": 0,
"type": "VariableDeclaration"
}
],
"end": 19,
"range": [
0,
19
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1 @@
let r = /[0-9]+/;

View File

@ -0,0 +1,57 @@
{
"body": [
{
"declarations": [
{
"end": 16,
"id": {
"end": 5,
"name": "r",
"range": [
4,
5
],
"start": 4,
"type": "Identifier"
},
"init": {
"end": 16,
"range": [
8,
16
],
"regex": {
"flags": "",
"pattern": "[0-9]+"
},
"start": 8,
"type": "Literal",
"value": {}
},
"range": [
4,
16
],
"start": 4,
"type": "VariableDeclarator"
}
],
"end": 17,
"kind": "let",
"range": [
0,
17
],
"start": 0,
"type": "VariableDeclaration"
}
],
"end": 17,
"range": [
0,
17
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

View File

@ -0,0 +1,3 @@
#! /usr/bin/env node
const x = "abc";

View File

@ -0,0 +1,54 @@
{
"body": [
{
"declarations": [
{
"end": 37,
"id": {
"end": 29,
"name": "x",
"range": [
28,
29
],
"start": 28,
"type": "Identifier"
},
"init": {
"end": 37,
"range": [
32,
37
],
"raw": "abc",
"start": 32,
"type": "Literal",
"value": "abc"
},
"range": [
28,
37
],
"start": 28,
"type": "VariableDeclarator"
}
],
"end": 38,
"kind": "const",
"range": [
22,
38
],
"start": 22,
"type": "VariableDeclaration"
}
],
"end": 38,
"range": [
0,
38
],
"sourceType": "script",
"start": 0,
"type": "Program"
}

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