mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 04:52:26 -05:00
WIP
This commit is contained in:
parent
9124e0a0df
commit
fd600e0dab
8 changed files with 2145 additions and 884 deletions
|
@ -38,12 +38,20 @@ const PropFlags = {
|
|||
* the string table that was included in the message.
|
||||
*/
|
||||
String: 2,
|
||||
/**
|
||||
* A numnber field. Numbers are represented as strings internally.
|
||||
*/
|
||||
Number: 3,
|
||||
/** This value is either 0 = false, or 1 = true */
|
||||
Bool: 3,
|
||||
Bool: 4,
|
||||
/** No value, it's null */
|
||||
Null: 4,
|
||||
Null: 5,
|
||||
/** No value, it's undefined */
|
||||
Undefined: 5,
|
||||
Undefined: 6,
|
||||
/** An object */
|
||||
Obj: 7,
|
||||
/** A regex obj */
|
||||
Regex: 8,
|
||||
};
|
||||
|
||||
/** @typedef {import("./40_lint_types.d.ts").AstContext} AstContext */
|
||||
|
@ -291,18 +299,28 @@ function findPropOffset(buf, offset, search) {
|
|||
const propCount = buf[offset];
|
||||
offset += 1;
|
||||
|
||||
let skip = 0;
|
||||
|
||||
for (let i = 0; i < propCount; i++) {
|
||||
const maybe = offset;
|
||||
const prop = buf[offset++];
|
||||
const kind = buf[offset++];
|
||||
if (prop === search) return maybe;
|
||||
if (skip === 0 && prop === search) return maybe;
|
||||
if (skip > 0) skip--;
|
||||
|
||||
if (kind === PropFlags.Ref) {
|
||||
offset += 4;
|
||||
} else if (kind === PropFlags.RefArr) {
|
||||
const len = readU32(buf, offset);
|
||||
offset += 4 + (len * 4);
|
||||
} else if (kind === PropFlags.String) {
|
||||
} else if (kind === PropFlags.Obj) {
|
||||
const len = readU32(buf, offset);
|
||||
skip += len;
|
||||
offset += 4;
|
||||
} else if (
|
||||
kind === PropFlags.String || kind === PropFlags.Number ||
|
||||
kind === PropFlags.Regex
|
||||
) {
|
||||
offset += 4;
|
||||
} else if (kind === PropFlags.Bool) {
|
||||
offset++;
|
||||
|
@ -398,6 +416,10 @@ function toJsValue(ctx, offset) {
|
|||
range: readValue(ctx, offset, AST_PROP_RANGE),
|
||||
};
|
||||
|
||||
/** @type {Record<string, any>} */
|
||||
let out = node;
|
||||
let skip = 0;
|
||||
|
||||
// type + parentId + SpanLo + SpanHi
|
||||
offset += 1 + 4 + 4 + 4;
|
||||
|
||||
|
@ -406,11 +428,18 @@ function toJsValue(ctx, offset) {
|
|||
const prop = buf[offset++];
|
||||
const kind = buf[offset++];
|
||||
const name = getString(ctx.strTable, ctx.strByProp[prop]);
|
||||
if (skip > 0) {
|
||||
skip--;
|
||||
if (skip === 0) {
|
||||
// TODO(@marvinhagemeister): Support recursiveness
|
||||
out = node;
|
||||
}
|
||||
}
|
||||
|
||||
if (kind === PropFlags.Ref) {
|
||||
const v = readU32(buf, offset);
|
||||
offset += 4;
|
||||
node[name] = v === 0 ? null : toJsValue(ctx, v);
|
||||
out[name] = v === 0 ? null : toJsValue(ctx, v);
|
||||
} else if (kind === PropFlags.RefArr) {
|
||||
const len = readU32(buf, offset);
|
||||
offset += 4;
|
||||
|
@ -421,24 +450,126 @@ function toJsValue(ctx, offset) {
|
|||
nodes[i] = toJsValue(ctx, v);
|
||||
offset += 4;
|
||||
}
|
||||
node[name] = nodes;
|
||||
out[name] = nodes;
|
||||
} else if (kind === PropFlags.Bool) {
|
||||
const v = buf[offset++];
|
||||
node[name] = v === 1;
|
||||
out[name] = v === 1;
|
||||
} else if (kind === PropFlags.String) {
|
||||
const v = readU32(buf, offset);
|
||||
offset += 4;
|
||||
node[name] = getString(ctx.strTable, v);
|
||||
out[name] = getString(ctx.strTable, v);
|
||||
} else if (kind === PropFlags.Number) {
|
||||
const v = readU32(buf, offset);
|
||||
offset += 4;
|
||||
out[name] = Number(getString(ctx.strTable, v));
|
||||
} else if (kind === PropFlags.Regex) {
|
||||
const v = readU32(buf, offset);
|
||||
offset += 4;
|
||||
|
||||
out[name] = readRegex(ctx.strTable, v);
|
||||
} else if (kind === PropFlags.Null) {
|
||||
node[name] = null;
|
||||
out[name] = null;
|
||||
} else if (kind === PropFlags.Undefined) {
|
||||
node[name] = undefined;
|
||||
out[name] = undefined;
|
||||
} else if (kind === PropFlags.Obj) {
|
||||
const v = readU32(buf, offset);
|
||||
skip += v;
|
||||
offset += 4;
|
||||
const obj = {};
|
||||
out = obj;
|
||||
out[name] = obj;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AstContext["strTable"]} strTable
|
||||
* @param {number} strId
|
||||
* @returns {RegExp}
|
||||
*/
|
||||
function readRegex(strTable, strId) {
|
||||
const raw = getString(strTable, strId);
|
||||
const idx = raw.lastIndexOf("/");
|
||||
const pattern = raw.slice(1, idx);
|
||||
const flags = idx < raw.length - 1 ? raw.slice(idx) : undefined;
|
||||
|
||||
return new RegExp(pattern, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AstContext} ctx
|
||||
* @param {number} offset
|
||||
* @returns {Record<string, any>}
|
||||
*/
|
||||
function readObject(ctx, offset) {
|
||||
const { buf, strTable, strByProp } = ctx;
|
||||
|
||||
/** @type {Record<string, any>} */
|
||||
const obj = {};
|
||||
|
||||
const count = readU32(buf, offset);
|
||||
offset += 4;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const start = offset;
|
||||
const prop = buf[offset++];
|
||||
const name = getString(strTable, strByProp[prop]);
|
||||
const value = readProperty(ctx, start);
|
||||
|
||||
obj[name] = value;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AstContext} ctx
|
||||
* @param {number} offset
|
||||
* @returns {any}
|
||||
*/
|
||||
function readProperty(ctx, offset) {
|
||||
const { buf } = ctx;
|
||||
|
||||
const kind = buf[offset + 1];
|
||||
offset += 2;
|
||||
|
||||
if (kind === PropFlags.Ref) {
|
||||
const value = readU32(buf, offset);
|
||||
return getNode(ctx, value);
|
||||
} else if (kind === PropFlags.RefArr) {
|
||||
const len = readU32(buf, offset);
|
||||
offset += 4;
|
||||
|
||||
const nodes = new Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
nodes[i] = getNode(ctx, readU32(buf, offset));
|
||||
offset += 4;
|
||||
}
|
||||
return nodes;
|
||||
} else if (kind === PropFlags.Bool) {
|
||||
return buf[offset] === 1;
|
||||
} else if (kind === PropFlags.String) {
|
||||
const v = readU32(buf, offset);
|
||||
return getString(ctx.strTable, v);
|
||||
} else if (kind === PropFlags.Number) {
|
||||
const v = readU32(buf, offset);
|
||||
return Number(getString(ctx.strTable, v));
|
||||
} else if (kind === PropFlags.Regex) {
|
||||
const v = readU32(buf, offset);
|
||||
return readRegex(ctx.strTable, v);
|
||||
} else if (kind === PropFlags.Null) {
|
||||
return null;
|
||||
} else if (kind === PropFlags.Undefined) {
|
||||
return undefined;
|
||||
} else if (kind === PropFlags.Obj) {
|
||||
return readObject(ctx, offset);
|
||||
}
|
||||
|
||||
throw new Error(`Unknown prop kind: ${kind}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a specific property from a node
|
||||
* @param {AstContext} ctx
|
||||
|
@ -464,34 +595,7 @@ function readValue(ctx, offset, search) {
|
|||
offset = findPropOffset(ctx.buf, offset, search);
|
||||
if (offset === -1) return undefined;
|
||||
|
||||
const kind = buf[offset + 1];
|
||||
offset += 2;
|
||||
|
||||
if (kind === PropFlags.Ref) {
|
||||
const value = readU32(buf, offset);
|
||||
return getNode(ctx, value);
|
||||
} else if (kind === PropFlags.RefArr) {
|
||||
const len = readU32(buf, offset);
|
||||
offset += 4;
|
||||
|
||||
const nodes = new Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
nodes[i] = getNode(ctx, readU32(buf, offset));
|
||||
offset += 4;
|
||||
}
|
||||
return nodes;
|
||||
} else if (kind === PropFlags.Bool) {
|
||||
return buf[offset] === 1;
|
||||
} else if (kind === PropFlags.String) {
|
||||
const v = readU32(buf, offset);
|
||||
return getString(ctx.strTable, v);
|
||||
} else if (kind === PropFlags.Null) {
|
||||
return null;
|
||||
} else if (kind === PropFlags.Undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
throw new Error(`Unknown prop kind: ${kind}`);
|
||||
return readProperty(ctx, offset);
|
||||
}
|
||||
|
||||
const DECODER = new TextDecoder();
|
||||
|
@ -564,7 +668,9 @@ function findChildOffset(buf, child) {
|
|||
|
||||
break;
|
||||
}
|
||||
case PropFlags.Number:
|
||||
case PropFlags.String:
|
||||
case PropFlags.Regex:
|
||||
offset += 4;
|
||||
break;
|
||||
case PropFlags.Bool:
|
||||
|
@ -573,6 +679,8 @@ function findChildOffset(buf, child) {
|
|||
case PropFlags.Null:
|
||||
case PropFlags.Undefined:
|
||||
break;
|
||||
case PropFlags.Obj:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -656,6 +764,12 @@ class MatchCtx {
|
|||
if (kind === PropFlags.String) {
|
||||
const s = readU32(buf, offset);
|
||||
return getString(this.strTable, s);
|
||||
} else if (kind === PropFlags.Number) {
|
||||
const s = readU32(buf, offset);
|
||||
return Number(getString(this.strTable, s));
|
||||
} else if (kind === PropFlags.Regex) {
|
||||
const v = readU32(buf, offset);
|
||||
return readRegex(this.strTable, v);
|
||||
} else if (kind === PropFlags.Bool) {
|
||||
return buf[offset] === 1;
|
||||
} else if (kind === PropFlags.Null) {
|
||||
|
@ -747,7 +861,9 @@ class MatchCtx {
|
|||
return len;
|
||||
}
|
||||
|
||||
case PropFlags.Number:
|
||||
case PropFlags.String:
|
||||
case PropFlags.Regex:
|
||||
offset += 4;
|
||||
break;
|
||||
case PropFlags.Bool:
|
||||
|
@ -799,6 +915,8 @@ class MatchCtx {
|
|||
}
|
||||
|
||||
case PropFlags.String:
|
||||
case PropFlags.Number:
|
||||
case PropFlags.Regex:
|
||||
offset += 4;
|
||||
break;
|
||||
case PropFlags.Bool:
|
||||
|
@ -1133,7 +1251,10 @@ function traverse(ctx, visitors, offset, cancellationToken) {
|
|||
offset += 4;
|
||||
traverse(ctx, visitors, child, cancellationToken);
|
||||
}
|
||||
} else if (kind === PropFlags.String) {
|
||||
} else if (
|
||||
kind === PropFlags.String || kind === PropFlags.Number ||
|
||||
kind === PropFlags.Regex
|
||||
) {
|
||||
offset += 4;
|
||||
} else if (kind === PropFlags.Bool) {
|
||||
offset += 1;
|
||||
|
@ -1257,6 +1378,22 @@ function _dump(ctx) {
|
|||
console.log(
|
||||
` ${name}: ${getString(ctx.strTable, v)} (${kindName}, ${prop})`,
|
||||
);
|
||||
} else if (kind === PropFlags.Number) {
|
||||
const v = readU32(buf, offset);
|
||||
offset += 4;
|
||||
// @ts-ignore dump fn
|
||||
// deno-lint-ignore no-console
|
||||
console.log(
|
||||
` ${name}: ${getString(ctx.strTable, v)} (${kindName}, ${prop})`,
|
||||
);
|
||||
} else if (kind === PropFlags.Regex) {
|
||||
const v = readU32(buf, offset);
|
||||
offset += 4;
|
||||
// @ts-ignore dump fn
|
||||
// deno-lint-ignore no-console
|
||||
console.log(
|
||||
` ${name}: ${getString(ctx.strTable, v)} (${kindName}, ${prop})`,
|
||||
);
|
||||
} else if (kind === PropFlags.Null) {
|
||||
// @ts-ignore dump fn
|
||||
// deno-lint-ignore no-console
|
||||
|
|
|
@ -14,9 +14,12 @@ pub enum PropFlags {
|
|||
Ref,
|
||||
RefArr,
|
||||
String,
|
||||
Number,
|
||||
Bool,
|
||||
Null,
|
||||
Undefined,
|
||||
Obj,
|
||||
Regex,
|
||||
}
|
||||
|
||||
impl From<PropFlags> for u8 {
|
||||
|
@ -33,9 +36,12 @@ impl TryFrom<u8> for PropFlags {
|
|||
0 => Ok(PropFlags::Ref),
|
||||
1 => Ok(PropFlags::RefArr),
|
||||
2 => Ok(PropFlags::String),
|
||||
3 => Ok(PropFlags::Bool),
|
||||
4 => Ok(PropFlags::Null),
|
||||
5 => Ok(PropFlags::Undefined),
|
||||
3 => Ok(PropFlags::Number),
|
||||
4 => Ok(PropFlags::Bool),
|
||||
5 => Ok(PropFlags::Null),
|
||||
6 => Ok(PropFlags::Undefined),
|
||||
7 => Ok(PropFlags::Obj),
|
||||
8 => Ok(PropFlags::Regex),
|
||||
_ => Err("Unknown Prop flag"),
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +143,14 @@ pub struct StrPos(pub usize);
|
|||
pub struct UndefPos(pub usize);
|
||||
#[derive(Debug)]
|
||||
pub struct NullPos(pub usize);
|
||||
#[derive(Debug)]
|
||||
pub struct NumPos(pub usize);
|
||||
#[derive(Debug)]
|
||||
pub struct ObjPos(pub usize);
|
||||
#[derive(Debug)]
|
||||
pub struct RegexPos(pub usize);
|
||||
|
||||
pub struct AllocNode(pub usize, pub usize);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum NodePos {
|
||||
|
@ -149,6 +163,12 @@ pub enum NodePos {
|
|||
Undef(UndefPos),
|
||||
#[allow(dead_code)]
|
||||
Null(NullPos),
|
||||
#[allow(dead_code)]
|
||||
Num(NumPos),
|
||||
#[allow(dead_code)]
|
||||
Obj(ObjPos),
|
||||
#[allow(dead_code)]
|
||||
Regex(RegexPos),
|
||||
}
|
||||
|
||||
pub trait AstBufSerializer<K, P>
|
||||
|
@ -160,11 +180,13 @@ where
|
|||
-> PendingNodeRef;
|
||||
fn ref_field(&mut self, prop: P) -> FieldPos;
|
||||
fn ref_vec_field(&mut self, prop: P, len: usize) -> FieldArrPos;
|
||||
fn obj_field(&mut self, prop: P, len: usize) -> ObjPos;
|
||||
fn str_field(&mut self, prop: P) -> StrPos;
|
||||
fn num_field(&mut self, prop: P) -> NumPos;
|
||||
fn bool_field(&mut self, prop: P) -> BoolPos;
|
||||
fn undefined_field(&mut self, prop: P) -> UndefPos;
|
||||
#[allow(dead_code)]
|
||||
fn null_field(&mut self, prop: P) -> NullPos;
|
||||
fn regex_field(&mut self, prop: P) -> RegexPos;
|
||||
fn commit_schema(&mut self, offset: PendingNodeRef) -> NodeRef;
|
||||
|
||||
fn write_ref(&mut self, pos: FieldPos, value: NodeRef);
|
||||
|
@ -172,17 +194,27 @@ where
|
|||
fn write_refs(&mut self, pos: FieldArrPos, value: Vec<NodeRef>);
|
||||
fn write_str(&mut self, pos: StrPos, value: &str);
|
||||
fn write_bool(&mut self, pos: BoolPos, value: bool);
|
||||
fn write_num(&mut self, pos: NumPos, value: &str);
|
||||
fn write_regex(&mut self, pos: RegexPos, value: &str);
|
||||
|
||||
fn serialize(&mut self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SerializeCtx {
|
||||
buf: Vec<u8>,
|
||||
id: u32,
|
||||
|
||||
start_buf: NodeRef,
|
||||
|
||||
buf: Vec<u8>,
|
||||
field_buf: Vec<u8>,
|
||||
schema_map: Vec<usize>,
|
||||
spans: Vec<u8>,
|
||||
str_table: StringTable,
|
||||
kind_map: Vec<usize>,
|
||||
prop_map: Vec<usize>,
|
||||
kind_name_map: Vec<usize>,
|
||||
prop_name_map: Vec<usize>,
|
||||
|
||||
// Internal, used for creating schemas
|
||||
field_count: u8,
|
||||
}
|
||||
|
||||
|
@ -198,19 +230,23 @@ impl SerializeCtx {
|
|||
let kind_size = kind_len as usize;
|
||||
let prop_size = prop_len as usize;
|
||||
let mut ctx = Self {
|
||||
id: 0,
|
||||
spans: vec![],
|
||||
start_buf: NodeRef(0),
|
||||
buf: vec![],
|
||||
field_buf: vec![],
|
||||
schema_map: vec![0; kind_size],
|
||||
str_table: StringTable::new(),
|
||||
kind_map: vec![0; kind_size],
|
||||
prop_map: vec![0; prop_size],
|
||||
kind_name_map: vec![0; kind_size],
|
||||
prop_name_map: vec![0; prop_size],
|
||||
field_count: 0,
|
||||
};
|
||||
|
||||
let empty_str = ctx.str_table.insert("");
|
||||
|
||||
// Placeholder node is always 0
|
||||
ctx.append_node(0, NodeRef(0), &DUMMY_SP, 0);
|
||||
ctx.kind_map[0] = empty_str;
|
||||
ctx.reserve_props(0, NodeRef(0), &DUMMY_SP, 0);
|
||||
ctx.kind_name_map[0] = empty_str;
|
||||
ctx.start_buf = NodeRef(ctx.buf.len());
|
||||
|
||||
// Insert default props that are always present
|
||||
|
@ -220,15 +256,23 @@ impl SerializeCtx {
|
|||
let length_str = ctx.str_table.insert("length");
|
||||
|
||||
// These values are expected to be in this order on the JS side
|
||||
ctx.prop_map[0] = empty_str;
|
||||
ctx.prop_map[1] = type_str;
|
||||
ctx.prop_map[2] = parent_str;
|
||||
ctx.prop_map[3] = range_str;
|
||||
ctx.prop_map[4] = length_str;
|
||||
ctx.prop_name_map[0] = empty_str;
|
||||
ctx.prop_name_map[1] = type_str;
|
||||
ctx.prop_name_map[2] = parent_str;
|
||||
ctx.prop_name_map[3] = range_str;
|
||||
ctx.prop_name_map[4] = length_str;
|
||||
|
||||
ctx
|
||||
}
|
||||
|
||||
pub fn has_schema<N>(&self, kind: &N) -> bool
|
||||
where
|
||||
N: Into<u8> + Display + Clone,
|
||||
{
|
||||
let n: u8 = kind.clone().into();
|
||||
self.schema_map.get(n).is_none()
|
||||
}
|
||||
|
||||
/// Allocate a node's header
|
||||
fn field_header<P>(&mut self, prop: P, prop_flags: PropFlags) -> usize
|
||||
where
|
||||
|
@ -241,10 +285,10 @@ impl SerializeCtx {
|
|||
let n: u8 = prop.clone().into();
|
||||
self.buf.push(n);
|
||||
|
||||
if let Some(v) = self.prop_map.get::<usize>(n.into()) {
|
||||
if let Some(v) = self.prop_name_map.get::<usize>(n.into()) {
|
||||
if *v == 0 {
|
||||
let id = self.str_table.insert(&format!("{prop}"));
|
||||
self.prop_map[n as usize] = id;
|
||||
self.prop_name_map[n as usize] = id;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,25 +310,15 @@ impl SerializeCtx {
|
|||
offset
|
||||
}
|
||||
|
||||
fn append_node(
|
||||
&mut self,
|
||||
kind: u8,
|
||||
parent: NodeRef,
|
||||
span: &Span,
|
||||
prop_count: usize,
|
||||
) -> PendingNodeRef {
|
||||
fn get_id(&mut self) -> u32 {
|
||||
let id = self.id;
|
||||
self.id += 1;
|
||||
id
|
||||
}
|
||||
|
||||
fn reserve_props(&mut self, prop_count: usize) -> PendingNodeRef {
|
||||
let offset = self.buf.len();
|
||||
|
||||
// Node type fits in a u8
|
||||
self.buf.push(kind);
|
||||
|
||||
// Offset to the parent node. Will be 0 if none exists
|
||||
append_usize(&mut self.buf, parent.0);
|
||||
|
||||
// Span, the start and end location of this node
|
||||
append_u32(&mut self.buf, span.lo.0);
|
||||
append_u32(&mut self.buf, span.hi.0);
|
||||
|
||||
// No node has more than <10 properties
|
||||
debug_assert!(prop_count < 10);
|
||||
self.buf.push(prop_count as u8);
|
||||
|
@ -292,24 +326,76 @@ impl SerializeCtx {
|
|||
PendingNodeRef(NodeRef(offset))
|
||||
}
|
||||
|
||||
pub fn commit_schema(&mut self, node_ref: PendingNodeRef) -> NodeRef {
|
||||
let mut offset = node_ref.0 .0;
|
||||
/// The node buffer contains enough information for traversal
|
||||
/// <type u8>
|
||||
/// <id u32>
|
||||
/// <parent offset u32>
|
||||
/// <child offset u32>
|
||||
/// <next offset u32>
|
||||
pub fn append_node<N>(
|
||||
&mut self,
|
||||
kind: &N,
|
||||
parent: NodeRef,
|
||||
span: &Span,
|
||||
) -> NodeRef
|
||||
where
|
||||
N: Into<u8> + Display + Clone,
|
||||
{
|
||||
let offset = NodeRef(self.buf.len());
|
||||
let n = kind.clone().into();
|
||||
self.buf.push(n);
|
||||
|
||||
// type + parentId + span lo + span hi
|
||||
offset += 1 + 4 + 4 + 4;
|
||||
let id = self.get_id();
|
||||
append_u32(&mut self.buf, id);
|
||||
|
||||
self.buf[offset] = self.field_count;
|
||||
// Offset to the parent node. Will be 0 if none exists
|
||||
append_usize(&mut self.buf, parent.0);
|
||||
|
||||
// Reserve child
|
||||
append_usize(&mut self.buf, 0);
|
||||
|
||||
// Reserve next
|
||||
append_usize(&mut self.buf, 0);
|
||||
|
||||
// Append span
|
||||
append_u32(&mut self.spans, span.lo.0);
|
||||
append_u32(&mut self.spans, span.hi.0);
|
||||
|
||||
offset
|
||||
}
|
||||
|
||||
pub fn get_alloc_pos(&self) -> AllocNode {
|
||||
AllocNode(self.buf.len(), self.field_buf.len())
|
||||
}
|
||||
|
||||
pub fn begin_schema<N>(&mut self, kind: &N) -> usize
|
||||
where
|
||||
N: Into<u8> + Display + Clone,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if self.field_count > 0 {
|
||||
panic!("Uncommitted schema");
|
||||
}
|
||||
}
|
||||
|
||||
let offset = self.field_buf.len();
|
||||
|
||||
let n = usize::try_from(kind.clone().into());
|
||||
self.schema_map[n] = offset;
|
||||
|
||||
// prop count
|
||||
self.field_buf.push(0);
|
||||
|
||||
offset
|
||||
}
|
||||
|
||||
pub fn commit_schema(&mut self, offset: usize) {
|
||||
self.field_buf[offset] = self.field_count;
|
||||
self.field_count = 0;
|
||||
|
||||
node_ref.0
|
||||
}
|
||||
|
||||
/// Allocate the node header. It's always the same for every node.
|
||||
/// <type u8>
|
||||
/// <parent offset u32>
|
||||
/// <span lo u32>
|
||||
/// <span high u32>
|
||||
/// <property count u8> (There is no node with more than 10 properties)
|
||||
pub fn header<N>(
|
||||
&mut self,
|
||||
kind: N,
|
||||
|
@ -319,18 +405,21 @@ impl SerializeCtx {
|
|||
where
|
||||
N: Into<u8> + Display + Clone,
|
||||
{
|
||||
let n: u8 = kind.clone().into();
|
||||
let kind_u8: u8 = kind.clone().into();
|
||||
|
||||
if let Some(v) = self.kind_map.get::<usize>(n.into()) {
|
||||
if let Some(v) = self.kind_name_map.get::<usize>(kind_u8.into()) {
|
||||
if *v == 0 {
|
||||
let id = self.str_table.insert(&format!("{kind}"));
|
||||
self.kind_map[n as usize] = id;
|
||||
self.kind_name_map[kind_u8 as usize] = id;
|
||||
}
|
||||
}
|
||||
|
||||
self.append_node(kind_u8, parent);
|
||||
self.append_span(span);
|
||||
|
||||
// Prop count will be filled with the actual value when the
|
||||
// schema is committed.
|
||||
self.append_node(n, parent, span, 0)
|
||||
self.reserve_props(kind_u8, 0)
|
||||
}
|
||||
|
||||
/// Allocate a reference property that will hold the offset of
|
||||
|
@ -344,15 +433,20 @@ impl SerializeCtx {
|
|||
|
||||
/// Allocate a property that is a vec of node offsets pointing to other
|
||||
/// nodes.
|
||||
pub fn ref_vec_field<P>(&mut self, prop: P, len: usize) -> usize
|
||||
pub fn ref_vec_field<P>(&mut self, prop: P) -> usize
|
||||
where
|
||||
P: Into<u8> + Display + Clone,
|
||||
{
|
||||
let offset = self.field(prop, PropFlags::RefArr);
|
||||
self.field(prop, PropFlags::RefArr)
|
||||
}
|
||||
|
||||
for _ in 0..len {
|
||||
append_u32(&mut self.buf, 0);
|
||||
}
|
||||
// Allocate a number field. Numbers are internally represented as strings
|
||||
pub fn obj_field<P>(&mut self, prop: P, len: usize) -> usize
|
||||
where
|
||||
P: Into<u8> + Display + Clone,
|
||||
{
|
||||
let offset = self.field(prop, PropFlags::Obj);
|
||||
append_usize(&mut self.buf, len);
|
||||
|
||||
offset
|
||||
}
|
||||
|
@ -366,6 +460,22 @@ impl SerializeCtx {
|
|||
self.field(prop, PropFlags::String)
|
||||
}
|
||||
|
||||
// Allocate a number field. Numbers are internally represented as strings
|
||||
pub fn num_field<P>(&mut self, prop: P) -> usize
|
||||
where
|
||||
P: Into<u8> + Display + Clone,
|
||||
{
|
||||
self.field(prop, PropFlags::Number)
|
||||
}
|
||||
|
||||
// Allocate a regex field. Regexes are internally represented as strings
|
||||
pub fn regex_field<P>(&mut self, prop: P) -> usize
|
||||
where
|
||||
P: Into<u8> + Display + Clone,
|
||||
{
|
||||
self.field(prop, PropFlags::Regex)
|
||||
}
|
||||
|
||||
/// Allocate a bool field
|
||||
pub fn bool_field<P>(&mut self, prop: P) -> usize
|
||||
where
|
||||
|
@ -393,49 +503,25 @@ impl SerializeCtx {
|
|||
self.field_header(prop, PropFlags::Null)
|
||||
}
|
||||
|
||||
pub fn begin_write(&mut self, offset: &NodeRef) {
|
||||
//
|
||||
}
|
||||
|
||||
/// Replace the placeholder of a reference field with the actual offset
|
||||
/// to the node we want to point to.
|
||||
pub fn write_ref(&mut self, field_offset: usize, value: NodeRef) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let value_kind = self.buf[field_offset + 1];
|
||||
if PropFlags::try_from(value_kind).unwrap() != PropFlags::Ref {
|
||||
panic!("Trying to write a ref into a non-ref field")
|
||||
}
|
||||
}
|
||||
|
||||
write_usize(&mut self.buf, value.0, field_offset + 2);
|
||||
pub fn write_ref(&mut self, value: NodeRef) {
|
||||
append_usize(&mut self.buf, value.0);
|
||||
}
|
||||
|
||||
/// Helper for writing optional node offsets
|
||||
pub fn write_maybe_ref(
|
||||
&mut self,
|
||||
field_offset: usize,
|
||||
value: Option<NodeRef>,
|
||||
) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let value_kind = self.buf[field_offset + 1];
|
||||
if PropFlags::try_from(value_kind).unwrap() != PropFlags::Ref {
|
||||
panic!("Trying to write a ref into a non-ref field")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_maybe_ref(&mut self, value: Option<NodeRef>) {
|
||||
let ref_value = if let Some(v) = value { v } else { NodeRef(0) };
|
||||
write_usize(&mut self.buf, ref_value.0, field_offset + 2);
|
||||
append_usize(&mut self.buf, ref_value.0);
|
||||
}
|
||||
|
||||
/// Write a vec of node offsets into the property. The necessary space
|
||||
/// has been reserved earlier.
|
||||
pub fn write_refs(&mut self, field_offset: usize, value: Vec<NodeRef>) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let value_kind = self.buf[field_offset + 1];
|
||||
if PropFlags::try_from(value_kind).unwrap() != PropFlags::RefArr {
|
||||
panic!("Trying to write a ref into a non-ref array field")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_ref_vec(&mut self, value: Vec<NodeRef>) {
|
||||
let mut offset = field_offset + 2;
|
||||
write_usize(&mut self.buf, value.len(), offset);
|
||||
offset += 4;
|
||||
|
@ -448,30 +534,15 @@ impl SerializeCtx {
|
|||
|
||||
/// Store the string in our string table and save the id of the string
|
||||
/// in the current field.
|
||||
pub fn write_str(&mut self, field_offset: usize, value: &str) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let value_kind = self.buf[field_offset + 1];
|
||||
if PropFlags::try_from(value_kind).unwrap() != PropFlags::String {
|
||||
panic!("Trying to write a ref into a non-string field")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_str(&mut self, value: &str) {
|
||||
let id = self.str_table.insert(value);
|
||||
write_usize(&mut self.buf, id, field_offset + 2);
|
||||
append_usize(&mut self.field_buf, id);
|
||||
}
|
||||
|
||||
/// Write a bool to a field.
|
||||
pub fn write_bool(&mut self, field_offset: usize, value: bool) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let value_kind = self.buf[field_offset + 1];
|
||||
if PropFlags::try_from(value_kind).unwrap() != PropFlags::Bool {
|
||||
panic!("Trying to write a ref into a non-bool field")
|
||||
}
|
||||
}
|
||||
|
||||
self.buf[field_offset + 2] = if value { 1 } else { 0 };
|
||||
pub fn write_bool(&mut self, value: bool) {
|
||||
let n = if value { 1 } else { 0 };
|
||||
self.field_buf.push(n);
|
||||
}
|
||||
|
||||
/// Serialize all information we have into a buffer that can be sent to JS.
|
||||
|
@ -507,8 +578,8 @@ impl SerializeCtx {
|
|||
|
||||
// Write the total number of entries in the kind -> str mapping table
|
||||
// TODO: make this a u8
|
||||
append_usize(&mut buf, self.kind_map.len());
|
||||
for v in &self.kind_map {
|
||||
append_usize(&mut buf, self.kind_name_map.len());
|
||||
for v in &self.kind_name_map {
|
||||
append_usize(&mut buf, *v);
|
||||
}
|
||||
|
||||
|
@ -517,8 +588,8 @@ impl SerializeCtx {
|
|||
// as u8.
|
||||
let offset_prop_map = buf.len();
|
||||
// Write the total number of entries in the kind -> str mapping table
|
||||
append_usize(&mut buf, self.prop_map.len());
|
||||
for v in &self.prop_map {
|
||||
append_usize(&mut buf, self.prop_name_map.len());
|
||||
for v in &self.prop_name_map {
|
||||
append_usize(&mut buf, *v);
|
||||
}
|
||||
|
||||
|
|
|
@ -247,9 +247,7 @@ fn serialize_stmt(
|
|||
) -> NodeRef {
|
||||
match stmt {
|
||||
Stmt::Block(node) => {
|
||||
let raw = ctx.header(AstNode::BlockStatement, parent, &node.span);
|
||||
let body_pos = ctx.ref_vec_field(AstProp::Body, node.stmts.len());
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_block_stmt(parent, &node.span);
|
||||
|
||||
let children = node
|
||||
.stmts
|
||||
|
@ -257,103 +255,64 @@ fn serialize_stmt(
|
|||
.map(|stmt| serialize_stmt(ctx, stmt, pos))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
ctx.write_refs(body_pos, children);
|
||||
|
||||
pos
|
||||
ctx.write_block_stmt(pos, children)
|
||||
}
|
||||
Stmt::Empty(_) => NodeRef(0),
|
||||
Stmt::Debugger(node) => {
|
||||
let raw = ctx.header(AstNode::DebuggerStatement, parent, &node.span);
|
||||
ctx.commit_schema(raw)
|
||||
}
|
||||
Stmt::Debugger(node) => ctx.alloc_debugger_stmt(parent, &node.span),
|
||||
Stmt::With(node) => {
|
||||
let raw = ctx.header(AstNode::WithStatement, parent, &node.span);
|
||||
let obj_pos = ctx.ref_field(AstProp::Object);
|
||||
let body_pos = ctx.ref_field(AstProp::Body);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_with_stmt(parent, &node.span);
|
||||
|
||||
let obj = serialize_expr(ctx, &node.obj, pos);
|
||||
let body = serialize_stmt(ctx, &node.body, pos);
|
||||
|
||||
ctx.write_ref(obj_pos, obj);
|
||||
ctx.write_ref(body_pos, body);
|
||||
|
||||
pos
|
||||
ctx.write_with_stmt(pos, obj, body)
|
||||
}
|
||||
Stmt::Return(node) => {
|
||||
let raw = ctx.header(AstNode::ReturnStatement, parent, &node.span);
|
||||
let arg_pos = ctx.ref_field(AstProp::Argument);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_return_stmt(parent, &node.span);
|
||||
|
||||
let arg = node.arg.as_ref().map(|arg| serialize_expr(ctx, arg, pos));
|
||||
ctx.write_maybe_ref(arg_pos, arg);
|
||||
|
||||
pos
|
||||
ctx.write_return_stmt(pos, arg)
|
||||
}
|
||||
Stmt::Labeled(node) => {
|
||||
let raw = ctx.header(AstNode::LabeledStatement, parent, &node.span);
|
||||
let label_pos = ctx.ref_field(AstProp::Label);
|
||||
let body_pos = ctx.ref_field(AstProp::Body);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_labeled_stmt(parent, &node.span);
|
||||
|
||||
let ident = serialize_ident(ctx, &node.label, pos);
|
||||
let stmt = serialize_stmt(ctx, &node.body, pos);
|
||||
|
||||
ctx.write_ref(label_pos, ident);
|
||||
ctx.write_ref(body_pos, stmt);
|
||||
|
||||
pos
|
||||
ctx.write_labeled_stmt(pos, ident, stmt)
|
||||
}
|
||||
Stmt::Break(node) => {
|
||||
let raw = ctx.header(AstNode::BreakStatement, parent, &node.span);
|
||||
let label_pos = ctx.ref_field(AstProp::Label);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_break_stmt(parent, &node.span);
|
||||
|
||||
let arg = node
|
||||
.label
|
||||
.as_ref()
|
||||
.map(|label| serialize_ident(ctx, label, pos));
|
||||
|
||||
ctx.write_maybe_ref(label_pos, arg);
|
||||
|
||||
pos
|
||||
ctx.write_break_stmt(pos, arg)
|
||||
}
|
||||
Stmt::Continue(node) => {
|
||||
let raw = ctx.header(AstNode::ContinueStatement, parent, &node.span);
|
||||
let label_pos = ctx.ref_field(AstProp::Label);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_continue_stmt(parent, &node.span);
|
||||
|
||||
let arg = node
|
||||
.label
|
||||
.as_ref()
|
||||
.map(|label| serialize_ident(ctx, label, pos));
|
||||
|
||||
ctx.write_maybe_ref(label_pos, arg);
|
||||
|
||||
pos
|
||||
ctx.write_continue_stmt(pos, arg)
|
||||
}
|
||||
Stmt::If(node) => {
|
||||
let raw = ctx.header(AstNode::IfStatement, parent, &node.span);
|
||||
let test_pos = ctx.ref_field(AstProp::Test);
|
||||
let cons_pos = ctx.ref_field(AstProp::Consequent);
|
||||
let alt_pos = ctx.ref_field(AstProp::Alternate);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_if_stmt(parent, &node.span);
|
||||
|
||||
let test = serialize_expr(ctx, node.test.as_ref(), pos);
|
||||
let cons = serialize_stmt(ctx, node.cons.as_ref(), pos);
|
||||
let alt = node.alt.as_ref().map(|alt| serialize_stmt(ctx, alt, pos));
|
||||
|
||||
ctx.write_ref(test_pos, test);
|
||||
ctx.write_ref(cons_pos, cons);
|
||||
ctx.write_maybe_ref(alt_pos, alt);
|
||||
|
||||
pos
|
||||
ctx.write_if_stmt(pos, test, cons, alt)
|
||||
}
|
||||
Stmt::Switch(node) => {
|
||||
let raw = ctx.header(AstNode::SwitchStatement, parent, &node.span);
|
||||
let disc_pos = ctx.ref_field(AstProp::Discriminant);
|
||||
let cases_pos = ctx.ref_vec_field(AstProp::Cases, node.cases.len());
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_switch_stmt(parent, &node.span);
|
||||
|
||||
let disc = serialize_expr(ctx, &node.discriminant, pos);
|
||||
|
||||
|
@ -361,11 +320,7 @@ fn serialize_stmt(
|
|||
.cases
|
||||
.iter()
|
||||
.map(|case| {
|
||||
let raw = ctx.header(AstNode::SwitchCase, pos, &case.span);
|
||||
let test_pos = ctx.ref_field(AstProp::Test);
|
||||
let cons_pos =
|
||||
ctx.ref_vec_field(AstProp::Consequent, case.cons.len());
|
||||
let case_pos = ctx.commit_schema(raw);
|
||||
let case_pos = ctx.alloc_switch_case(pos, &case.span);
|
||||
|
||||
let test = case
|
||||
.test
|
||||
|
@ -378,27 +333,16 @@ fn serialize_stmt(
|
|||
.map(|cons| serialize_stmt(ctx, cons, case_pos))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
ctx.write_maybe_ref(test_pos, test);
|
||||
ctx.write_refs(cons_pos, cons);
|
||||
|
||||
case_pos
|
||||
ctx.write_switch_case(pos, test, cons)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
ctx.write_ref(disc_pos, disc);
|
||||
ctx.write_refs(cases_pos, cases);
|
||||
|
||||
pos
|
||||
ctx.write_switch_stmt(pos, disc, cases)
|
||||
}
|
||||
Stmt::Throw(node) => {
|
||||
let raw = ctx.header(AstNode::ThrowStatement, parent, &node.span);
|
||||
let arg_pos = ctx.ref_field(AstProp::Argument);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
let pos = ctx.alloc_throw_stmt(parent, &node.span);
|
||||
let arg = serialize_expr(ctx, &node.arg, pos);
|
||||
ctx.write_ref(arg_pos, arg);
|
||||
|
||||
pos
|
||||
ctx.write_throw_stmt(pos, arg)
|
||||
}
|
||||
Stmt::Try(node) => {
|
||||
let raw = ctx.header(AstNode::TryStatement, parent, &node.span);
|
||||
|
@ -555,10 +499,7 @@ fn serialize_expr(
|
|||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
match expr {
|
||||
Expr::This(node) => {
|
||||
let raw = ctx.header(AstNode::ThisExpression, parent, &node.span);
|
||||
ctx.commit_schema(raw)
|
||||
}
|
||||
Expr::This(node) => ctx.alloc_this_expr(parent, &node.span),
|
||||
Expr::Array(node) => {
|
||||
let raw = ctx.header(AstNode::ArrayExpression, parent, &node.span);
|
||||
let elems_pos = ctx.ref_vec_field(AstProp::Elements, node.elems.len());
|
||||
|
@ -639,47 +580,33 @@ fn serialize_expr(
|
|||
pos
|
||||
}
|
||||
Expr::Unary(node) => {
|
||||
let raw = ctx.header(AstNode::UnaryExpression, parent, &node.span);
|
||||
let flag_pos = ctx.str_field(AstProp::Operator);
|
||||
let arg_pos = ctx.ref_field(AstProp::Argument);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_unary_expr(parent, &node.span);
|
||||
|
||||
let arg = serialize_expr(ctx, &node.arg, pos);
|
||||
let op = match node.op {
|
||||
UnaryOp::Minus => "-",
|
||||
UnaryOp::Plus => "+",
|
||||
UnaryOp::Bang => "!",
|
||||
UnaryOp::Tilde => "~",
|
||||
UnaryOp::TypeOf => "typeof",
|
||||
UnaryOp::Void => "void",
|
||||
UnaryOp::Delete => "delete",
|
||||
};
|
||||
|
||||
ctx.write_str(
|
||||
flag_pos,
|
||||
match node.op {
|
||||
UnaryOp::Minus => "-",
|
||||
UnaryOp::Plus => "+",
|
||||
UnaryOp::Bang => "!",
|
||||
UnaryOp::Tilde => "~",
|
||||
UnaryOp::TypeOf => "typeof",
|
||||
UnaryOp::Void => "void",
|
||||
UnaryOp::Delete => "delete",
|
||||
},
|
||||
);
|
||||
ctx.write_ref(arg_pos, arg);
|
||||
ctx.write_unary_expr(pos, op, arg);
|
||||
|
||||
pos
|
||||
}
|
||||
Expr::Update(node) => {
|
||||
let raw = ctx.header(AstNode::UpdateExpression, parent, &node.span);
|
||||
let prefix_pos = ctx.bool_field(AstProp::Prefix);
|
||||
let arg_pos = ctx.ref_field(AstProp::Argument);
|
||||
let op_ops = ctx.str_field(AstProp::Operator);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_update_expr(parent, &node.span);
|
||||
|
||||
let arg = serialize_expr(ctx, node.arg.as_ref(), pos);
|
||||
let op = match node.op {
|
||||
UpdateOp::PlusPlus => "++",
|
||||
UpdateOp::MinusMinus => "--",
|
||||
};
|
||||
|
||||
ctx.write_bool(prefix_pos, node.prefix);
|
||||
ctx.write_ref(arg_pos, arg);
|
||||
ctx.write_str(
|
||||
op_ops,
|
||||
match node.op {
|
||||
UpdateOp::PlusPlus => "++",
|
||||
UpdateOp::MinusMinus => "--",
|
||||
},
|
||||
);
|
||||
ctx.write_update_expr(pos, node.prefix, op, arg);
|
||||
|
||||
pos
|
||||
}
|
||||
|
@ -728,11 +655,7 @@ fn serialize_expr(
|
|||
pos
|
||||
}
|
||||
Expr::Assign(node) => {
|
||||
let raw = ctx.header(AstNode::AssignmentExpression, parent, &node.span);
|
||||
let op_pos = ctx.str_field(AstProp::Operator);
|
||||
let left_pos = ctx.ref_field(AstProp::Left);
|
||||
let right_pos = ctx.ref_field(AstProp::Right);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_assignment_expr(parent, &node.span);
|
||||
|
||||
let left = match &node.left {
|
||||
AssignTarget::Simple(simple_assign_target) => {
|
||||
|
@ -783,29 +706,26 @@ fn serialize_expr(
|
|||
|
||||
let right = serialize_expr(ctx, node.right.as_ref(), pos);
|
||||
|
||||
ctx.write_str(
|
||||
op_pos,
|
||||
match node.op {
|
||||
AssignOp::Assign => "=",
|
||||
AssignOp::AddAssign => "+=",
|
||||
AssignOp::SubAssign => "-=",
|
||||
AssignOp::MulAssign => "*=",
|
||||
AssignOp::DivAssign => "/=",
|
||||
AssignOp::ModAssign => "%=",
|
||||
AssignOp::LShiftAssign => "<<=",
|
||||
AssignOp::RShiftAssign => ">>=",
|
||||
AssignOp::ZeroFillRShiftAssign => ">>>=",
|
||||
AssignOp::BitOrAssign => "|=",
|
||||
AssignOp::BitXorAssign => "^=",
|
||||
AssignOp::BitAndAssign => "&=",
|
||||
AssignOp::ExpAssign => "**=",
|
||||
AssignOp::AndAssign => "&&=",
|
||||
AssignOp::OrAssign => "||=",
|
||||
AssignOp::NullishAssign => "??=",
|
||||
},
|
||||
);
|
||||
ctx.write_ref(left_pos, left);
|
||||
ctx.write_ref(right_pos, right);
|
||||
let op = match node.op {
|
||||
AssignOp::Assign => "=",
|
||||
AssignOp::AddAssign => "+=",
|
||||
AssignOp::SubAssign => "-=",
|
||||
AssignOp::MulAssign => "*=",
|
||||
AssignOp::DivAssign => "/=",
|
||||
AssignOp::ModAssign => "%=",
|
||||
AssignOp::LShiftAssign => "<<=",
|
||||
AssignOp::RShiftAssign => ">>=",
|
||||
AssignOp::ZeroFillRShiftAssign => ">>>=",
|
||||
AssignOp::BitOrAssign => "|=",
|
||||
AssignOp::BitXorAssign => "^=",
|
||||
AssignOp::BitAndAssign => "&=",
|
||||
AssignOp::ExpAssign => "**=",
|
||||
AssignOp::AndAssign => "&&=",
|
||||
AssignOp::OrAssign => "||=",
|
||||
AssignOp::NullishAssign => "??=",
|
||||
};
|
||||
|
||||
ctx.write_assignment_expr(pos, op, left, right);
|
||||
|
||||
pos
|
||||
}
|
||||
|
@ -838,19 +758,13 @@ fn serialize_expr(
|
|||
pos
|
||||
}
|
||||
Expr::Cond(node) => {
|
||||
let raw = ctx.header(AstNode::ConditionalExpression, parent, &node.span);
|
||||
let test_pos = ctx.ref_field(AstProp::Test);
|
||||
let cons_pos = ctx.ref_field(AstProp::Consequent);
|
||||
let alt_pos = ctx.ref_field(AstProp::Alternate);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_conditional_expr(parent, &node.span);
|
||||
|
||||
let test = serialize_expr(ctx, node.test.as_ref(), pos);
|
||||
let cons = serialize_expr(ctx, node.cons.as_ref(), pos);
|
||||
let alt = serialize_expr(ctx, node.alt.as_ref(), pos);
|
||||
|
||||
ctx.write_ref(test_pos, test);
|
||||
ctx.write_ref(cons_pos, cons);
|
||||
ctx.write_ref(alt_pos, alt);
|
||||
ctx.write_conditional_expr(pos, test, cons, alt);
|
||||
|
||||
pos
|
||||
}
|
||||
|
@ -937,9 +851,7 @@ fn serialize_expr(
|
|||
pos
|
||||
}
|
||||
Expr::Seq(node) => {
|
||||
let raw = ctx.header(AstNode::SequenceExpression, parent, &node.span);
|
||||
let exprs_pos = ctx.ref_vec_field(AstProp::Expressions, node.exprs.len());
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_sequence_expr(parent, &node.span);
|
||||
|
||||
let children = node
|
||||
.exprs
|
||||
|
@ -947,32 +859,25 @@ fn serialize_expr(
|
|||
.map(|expr| serialize_expr(ctx, expr, pos))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
ctx.write_refs(exprs_pos, children);
|
||||
ctx.write_sequence_expr(pos, children);
|
||||
|
||||
pos
|
||||
}
|
||||
Expr::Ident(node) => serialize_ident(ctx, node, parent),
|
||||
Expr::Lit(node) => serialize_lit(ctx, node, parent),
|
||||
Expr::Tpl(node) => {
|
||||
let raw = ctx.header(AstNode::TemplateLiteral, parent, &node.span);
|
||||
let quasis_pos = ctx.ref_vec_field(AstProp::Quasis, node.quasis.len());
|
||||
let exprs_pos = ctx.ref_vec_field(AstProp::Expressions, node.exprs.len());
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_template_lit(parent, &node.span);
|
||||
|
||||
let quasis = node
|
||||
.quasis
|
||||
.iter()
|
||||
.map(|quasi| {
|
||||
let raw = ctx.header(AstNode::TemplateElement, pos, &quasi.span);
|
||||
let tail_pos = ctx.bool_field(AstProp::Tail);
|
||||
let raw_pos = ctx.str_field(AstProp::Raw);
|
||||
let cooked_pos = ctx.str_field(AstProp::Cooked);
|
||||
let tpl_pos = ctx.commit_schema(raw);
|
||||
let tpl_pos = ctx.alloc_template_elem(pos, &quasi.span);
|
||||
|
||||
ctx.write_bool(tail_pos, quasi.tail);
|
||||
ctx.write_str(raw_pos, &quasi.raw);
|
||||
ctx.write_str(
|
||||
cooked_pos,
|
||||
ctx.write_template_elem(
|
||||
tpl_pos,
|
||||
quasi.tail,
|
||||
&quasi.raw,
|
||||
&quasi
|
||||
.cooked
|
||||
.as_ref()
|
||||
|
@ -989,30 +894,21 @@ fn serialize_expr(
|
|||
.map(|expr| serialize_expr(ctx, expr, pos))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
ctx.write_refs(quasis_pos, quasis);
|
||||
ctx.write_refs(exprs_pos, exprs);
|
||||
ctx.write_template_lit(pos, quasis, exprs);
|
||||
|
||||
pos
|
||||
}
|
||||
Expr::TaggedTpl(node) => {
|
||||
let raw =
|
||||
ctx.header(AstNode::TaggedTemplateExpression, parent, &node.span);
|
||||
let tag_pos = ctx.ref_field(AstProp::Tag);
|
||||
let type_arg_pos = ctx.ref_field(AstProp::TypeArguments);
|
||||
let quasi_pos = ctx.ref_field(AstProp::Quasi);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_tagged_template_expr(parent, &node.span);
|
||||
|
||||
let tag = serialize_expr(ctx, &node.tag, pos);
|
||||
|
||||
let type_param_id = node
|
||||
let type_param = node
|
||||
.type_params
|
||||
.clone()
|
||||
.map(|params| serialize_ts_param_inst(ctx, params.as_ref(), pos));
|
||||
let quasi = serialize_expr(ctx, &Expr::Tpl(*node.tpl.clone()), pos);
|
||||
|
||||
ctx.write_ref(tag_pos, tag);
|
||||
ctx.write_maybe_ref(type_arg_pos, type_param_id);
|
||||
ctx.write_ref(quasi_pos, quasi);
|
||||
ctx.write_tagged_template_expr(pos, tag, type_param, quasi);
|
||||
|
||||
pos
|
||||
}
|
||||
|
@ -1061,18 +957,14 @@ fn serialize_expr(
|
|||
ctx.commit_schema(raw)
|
||||
}
|
||||
Expr::Yield(node) => {
|
||||
let raw = ctx.header(AstNode::YieldExpression, parent, &node.span);
|
||||
let delegate_pos = ctx.bool_field(AstProp::Delegate);
|
||||
let arg_pos = ctx.ref_field(AstProp::Argument);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_yield_expr(parent, &node.span);
|
||||
|
||||
let arg = node
|
||||
.arg
|
||||
.as_ref()
|
||||
.map(|arg| serialize_expr(ctx, arg.as_ref(), pos));
|
||||
|
||||
ctx.write_bool(delegate_pos, node.delegate);
|
||||
ctx.write_maybe_ref(arg_pos, arg);
|
||||
ctx.write_yield_expr(pos, node.delegate, arg);
|
||||
|
||||
pos
|
||||
}
|
||||
|
@ -1081,13 +973,9 @@ fn serialize_expr(
|
|||
ctx.commit_schema(raw)
|
||||
}
|
||||
Expr::Await(node) => {
|
||||
let raw = ctx.header(AstNode::AwaitExpression, parent, &node.span);
|
||||
let arg_pos = ctx.ref_field(AstProp::Argument);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
let pos = ctx.alloc_await_expr(parent, &node.span);
|
||||
let arg = serialize_expr(ctx, node.arg.as_ref(), pos);
|
||||
|
||||
ctx.write_ref(arg_pos, arg);
|
||||
ctx.write_await_expr(pos, arg);
|
||||
|
||||
pos
|
||||
}
|
||||
|
@ -1100,7 +988,7 @@ fn serialize_expr(
|
|||
Expr::JSXNamespacedName(node) => {
|
||||
serialize_jsx_namespaced_name(ctx, node, parent)
|
||||
}
|
||||
Expr::JSXEmpty(node) => serialize_jsx_empty_expr(ctx, node, parent),
|
||||
Expr::JSXEmpty(node) => ctx.alloc_jsx_empty_expr(parent, &node.span),
|
||||
Expr::JSXElement(node) => serialize_jsx_element(ctx, node, parent),
|
||||
Expr::JSXFragment(node) => serialize_jsx_fragment(ctx, node, parent),
|
||||
Expr::TsTypeAssertion(node) => {
|
||||
|
@ -1118,14 +1006,14 @@ fn serialize_expr(
|
|||
pos
|
||||
}
|
||||
Expr::TsConstAssertion(node) => {
|
||||
let raw = ctx.header(AstNode::TsConstAssertion, parent, &node.span);
|
||||
let arg_pos = ctx.ref_field(AstProp::Argument);
|
||||
let raw = ctx.header(AstNode::TSAsExpression, parent, &node.span);
|
||||
let expr_pos = ctx.ref_field(AstProp::Expression);
|
||||
ctx.null_field(AstProp::TypeAnnotation);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
let arg = serialize_expr(ctx, node.expr.as_ref(), pos);
|
||||
let expr = serialize_expr(ctx, node.expr.as_ref(), pos);
|
||||
|
||||
// FIXME
|
||||
ctx.write_ref(arg_pos, arg);
|
||||
ctx.write_ref(expr_pos, expr);
|
||||
|
||||
pos
|
||||
}
|
||||
|
@ -1154,20 +1042,21 @@ fn serialize_expr(
|
|||
|
||||
pos
|
||||
}
|
||||
Expr::TsInstantiation(node) => {
|
||||
let raw = ctx.header(AstNode::TsInstantiation, parent, &node.span);
|
||||
let expr_pos = ctx.ref_field(AstProp::Expression);
|
||||
let type_args_pos = ctx.ref_field(AstProp::TypeArguments);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
Expr::TsInstantiation(_) => {
|
||||
// let raw = ctx.header(AstNode::TsInstantiation, parent, &node.span);
|
||||
// let expr_pos = ctx.ref_field(AstProp::Expression);
|
||||
// let type_args_pos = ctx.ref_field(AstProp::TypeArguments);
|
||||
// let pos = ctx.commit_schema(raw);
|
||||
|
||||
let expr = serialize_expr(ctx, node.expr.as_ref(), pos);
|
||||
// let expr = serialize_expr(ctx, node.expr.as_ref(), pos);
|
||||
|
||||
let type_arg = serialize_ts_param_inst(ctx, node.type_args.as_ref(), pos);
|
||||
// let type_arg = serialize_ts_param_inst(ctx, node.type_args.as_ref(), pos);
|
||||
|
||||
ctx.write_ref(expr_pos, expr);
|
||||
ctx.write_ref(type_args_pos, type_arg);
|
||||
// ctx.write_ref(expr_pos, expr);
|
||||
// ctx.write_ref(type_args_pos, type_arg);
|
||||
|
||||
pos
|
||||
// pos
|
||||
todo!()
|
||||
}
|
||||
Expr::TsSatisfies(node) => {
|
||||
let raw = ctx.header(AstNode::TSSatisfiesExpression, parent, &node.span);
|
||||
|
@ -1533,13 +1422,8 @@ fn serialize_ident(
|
|||
ident: &Ident,
|
||||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
let raw = ctx.header(AstNode::Identifier, parent, &ident.span);
|
||||
let name_pos = ctx.str_field(AstProp::Name);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
ctx.write_str(name_pos, ident.sym.as_str());
|
||||
|
||||
pos
|
||||
let pos = ctx.alloc_identifier(parent, &ident.span);
|
||||
ctx.write_identifier(pos, ident.sym.as_str(), false, None)
|
||||
}
|
||||
|
||||
fn serialize_module_exported_name(
|
||||
|
@ -2068,32 +1952,20 @@ fn serialize_jsx_element(
|
|||
node: &JSXElement,
|
||||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
let raw = ctx.header(AstNode::JSXElement, parent, &node.span);
|
||||
let open_pos = ctx.ref_field(AstProp::OpeningElement);
|
||||
let close_pos = ctx.ref_field(AstProp::ClosingElement);
|
||||
let children_pos = ctx.ref_vec_field(AstProp::Children, node.children.len());
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_jsx_elem(parent, &node.span);
|
||||
|
||||
let open = serialize_jsx_opening_element(ctx, &node.opening, pos);
|
||||
|
||||
let close = node.closing.as_ref().map(|closing| {
|
||||
let raw = ctx.header(AstNode::JSXClosingElement, pos, &closing.span);
|
||||
let name_pos = ctx.ref_field(AstProp::Name);
|
||||
let closing_pos = ctx.commit_schema(raw);
|
||||
let closing_pos = ctx.alloc_jsx_closing_elem(pos, &closing.span);
|
||||
|
||||
let name = serialize_jsx_element_name(ctx, &closing.name, closing_pos);
|
||||
ctx.write_ref(name_pos, name);
|
||||
|
||||
closing_pos
|
||||
ctx.write_jsx_closing_elem(closing_pos, name)
|
||||
});
|
||||
|
||||
let children = serialize_jsx_children(ctx, &node.children, pos);
|
||||
|
||||
ctx.write_ref(open_pos, open);
|
||||
ctx.write_maybe_ref(close_pos, close);
|
||||
ctx.write_refs(children_pos, children);
|
||||
|
||||
pos
|
||||
ctx.write_jsx_elem(pos, open, close, children)
|
||||
}
|
||||
|
||||
fn serialize_jsx_fragment(
|
||||
|
@ -2101,26 +1973,13 @@ fn serialize_jsx_fragment(
|
|||
node: &JSXFragment,
|
||||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
let raw = ctx.header(AstNode::JSXFragment, parent, &node.span);
|
||||
|
||||
let opening_pos = ctx.ref_field(AstProp::OpeningFragment);
|
||||
let closing_pos = ctx.ref_field(AstProp::ClosingFragment);
|
||||
let children_pos = ctx.ref_vec_field(AstProp::Children, node.children.len());
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
let raw = ctx.header(AstNode::JSXOpeningFragment, pos, &node.opening.span);
|
||||
let opening_id = ctx.commit_schema(raw);
|
||||
|
||||
let raw = ctx.header(AstNode::JSXClosingFragment, pos, &node.closing.span);
|
||||
let closing_id = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_jsx_frag(parent, &node.span);
|
||||
|
||||
let opening = ctx.alloc_jsx_opening_frag(pos, &node.opening.span);
|
||||
let closing = ctx.alloc_jsx_closing_frag(pos, &node.closing.span);
|
||||
let children = serialize_jsx_children(ctx, &node.children, pos);
|
||||
|
||||
ctx.write_ref(opening_pos, opening_id);
|
||||
ctx.write_ref(closing_pos, closing_id);
|
||||
ctx.write_refs(children_pos, children);
|
||||
|
||||
pos
|
||||
ctx.write_jsx_frag(pos, opening, closing, children)
|
||||
}
|
||||
|
||||
fn serialize_jsx_children(
|
||||
|
@ -2133,15 +1992,8 @@ fn serialize_jsx_children(
|
|||
.map(|child| {
|
||||
match child {
|
||||
JSXElementChild::JSXText(text) => {
|
||||
let raw = ctx.header(AstNode::JSXText, parent, &text.span);
|
||||
let raw_pos = ctx.str_field(AstProp::Raw);
|
||||
let value_pos = ctx.str_field(AstProp::Value);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
ctx.write_str(raw_pos, &text.raw);
|
||||
ctx.write_str(value_pos, &text.value);
|
||||
|
||||
pos
|
||||
let pos = ctx.alloc_jsx_text(parent, &text.span);
|
||||
ctx.write_jsx_text(pos, &text.raw, &text.value)
|
||||
}
|
||||
JSXElementChild::JSXExprContainer(container) => {
|
||||
serialize_jsx_container_expr(ctx, container, parent)
|
||||
|
@ -2164,10 +2016,7 @@ fn serialize_jsx_member_expr(
|
|||
node: &JSXMemberExpr,
|
||||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
let raw = ctx.header(AstNode::JSXMemberExpression, parent, &node.span);
|
||||
let obj_ref = ctx.ref_field(AstProp::Object);
|
||||
let prop_ref = ctx.ref_field(AstProp::Property);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_jsx_member_expr(parent, &node.span);
|
||||
|
||||
let obj = match &node.obj {
|
||||
JSXObject::JSXMemberExpr(member) => {
|
||||
|
@ -2178,10 +2027,7 @@ fn serialize_jsx_member_expr(
|
|||
|
||||
let prop = serialize_ident_name_as_jsx_identifier(ctx, &node.prop, pos);
|
||||
|
||||
ctx.write_ref(obj_ref, obj);
|
||||
ctx.write_ref(prop_ref, prop);
|
||||
|
||||
pos
|
||||
ctx.write_jsx_member_expr(pos, obj, prop)
|
||||
}
|
||||
|
||||
fn serialize_jsx_element_name(
|
||||
|
@ -2207,12 +2053,7 @@ fn serialize_jsx_opening_element(
|
|||
node: &JSXOpeningElement,
|
||||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
let raw = ctx.header(AstNode::JSXOpeningElement, parent, &node.span);
|
||||
let sclose_pos = ctx.bool_field(AstProp::SelfClosing);
|
||||
let name_pos = ctx.ref_field(AstProp::Name);
|
||||
let attrs_pos = ctx.ref_vec_field(AstProp::Attributes, node.attrs.len());
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
let pos = ctx.alloc_jsx_opening_elem(parent, &node.span);
|
||||
let name = serialize_jsx_element_name(ctx, &node.name, pos);
|
||||
|
||||
// FIXME: type args
|
||||
|
@ -2222,10 +2063,7 @@ fn serialize_jsx_opening_element(
|
|||
.iter()
|
||||
.map(|attr| match attr {
|
||||
JSXAttrOrSpread::JSXAttr(attr) => {
|
||||
let raw = ctx.header(AstNode::JSXAttribute, pos, &attr.span);
|
||||
let name_pos = ctx.ref_field(AstProp::Name);
|
||||
let value_pos = ctx.ref_field(AstProp::Value);
|
||||
let attr_pos = ctx.commit_schema(raw);
|
||||
let attr_pos = ctx.alloc_jsx_attr(pos, &attr.span);
|
||||
|
||||
let name = match &attr.name {
|
||||
JSXAttrName::Ident(name) => {
|
||||
|
@ -2249,30 +2087,17 @@ fn serialize_jsx_opening_element(
|
|||
}
|
||||
});
|
||||
|
||||
ctx.write_ref(name_pos, name);
|
||||
ctx.write_maybe_ref(value_pos, value);
|
||||
|
||||
attr_pos
|
||||
ctx.write_jsx_attr(attr_pos, name, value)
|
||||
}
|
||||
JSXAttrOrSpread::SpreadElement(spread) => {
|
||||
let raw = ctx.header(AstNode::JSXAttribute, pos, &spread.dot3_token);
|
||||
let arg_pos = ctx.ref_field(AstProp::Argument);
|
||||
let attr_pos = ctx.commit_schema(raw);
|
||||
|
||||
let attr_pos = ctx.alloc_jsx_spread_attr(pos, &spread.dot3_token);
|
||||
let arg = serialize_expr(ctx, &spread.expr, attr_pos);
|
||||
|
||||
ctx.write_ref(arg_pos, arg);
|
||||
|
||||
attr_pos
|
||||
ctx.write_jsx_spread_attr(attr_pos, arg)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
ctx.write_bool(sclose_pos, node.self_closing);
|
||||
ctx.write_ref(name_pos, name);
|
||||
ctx.write_refs(attrs_pos, attrs);
|
||||
|
||||
pos
|
||||
ctx.write_jsx_opening_elem(pos, node.self_closing, name, attrs)
|
||||
}
|
||||
|
||||
fn serialize_jsx_container_expr(
|
||||
|
@ -2280,27 +2105,14 @@ fn serialize_jsx_container_expr(
|
|||
node: &JSXExprContainer,
|
||||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
let raw = ctx.header(AstNode::JSXExpressionContainer, parent, &node.span);
|
||||
let expr_pos = ctx.ref_field(AstProp::Expression);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_jsx_expr_container(parent, &node.span);
|
||||
|
||||
let expr = match &node.expr {
|
||||
JSXExpr::JSXEmptyExpr(expr) => serialize_jsx_empty_expr(ctx, expr, pos),
|
||||
JSXExpr::JSXEmptyExpr(expr) => ctx.alloc_jsx_empty_expr(pos, &expr.span),
|
||||
JSXExpr::Expr(expr) => serialize_expr(ctx, expr, pos),
|
||||
};
|
||||
|
||||
ctx.write_ref(expr_pos, expr);
|
||||
|
||||
pos
|
||||
}
|
||||
|
||||
fn serialize_jsx_empty_expr(
|
||||
ctx: &mut TsEsTreeBuilder,
|
||||
node: &JSXEmptyExpr,
|
||||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
let raw = ctx.header(AstNode::JSXEmptyExpression, parent, &node.span);
|
||||
ctx.commit_schema(raw)
|
||||
ctx.write_jsx_expr_container(pos, expr)
|
||||
}
|
||||
|
||||
fn serialize_jsx_namespaced_name(
|
||||
|
@ -2308,18 +2120,12 @@ fn serialize_jsx_namespaced_name(
|
|||
node: &JSXNamespacedName,
|
||||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
let raw = ctx.header(AstNode::JSXNamespacedName, parent, &node.span);
|
||||
let ns_pos = ctx.ref_field(AstProp::Namespace);
|
||||
let name_pos = ctx.ref_field(AstProp::Name);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
let pos = ctx.alloc_jsx_namespaced_name(parent, &node.span);
|
||||
|
||||
let ns_id = serialize_ident_name_as_jsx_identifier(ctx, &node.ns, pos);
|
||||
let name_id = serialize_ident_name_as_jsx_identifier(ctx, &node.name, pos);
|
||||
let ns = serialize_ident_name_as_jsx_identifier(ctx, &node.ns, pos);
|
||||
let name = serialize_ident_name_as_jsx_identifier(ctx, &node.name, pos);
|
||||
|
||||
ctx.write_ref(ns_pos, ns_id);
|
||||
ctx.write_ref(name_pos, name_id);
|
||||
|
||||
pos
|
||||
ctx.write_jsx_namespaced_name(pos, ns, name)
|
||||
}
|
||||
|
||||
fn serialize_ident_name_as_jsx_identifier(
|
||||
|
@ -2327,13 +2133,8 @@ fn serialize_ident_name_as_jsx_identifier(
|
|||
node: &IdentName,
|
||||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
let raw = ctx.header(AstNode::JSXIdentifier, parent, &node.span);
|
||||
let name_pos = ctx.str_field(AstProp::Name);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
ctx.write_str(name_pos, &node.sym);
|
||||
|
||||
pos
|
||||
let pos = ctx.alloc_jsx_identifier(parent, &node.span);
|
||||
ctx.write_jsx_identifier(pos, &node.sym)
|
||||
}
|
||||
|
||||
fn serialize_jsx_identifier(
|
||||
|
@ -2341,13 +2142,8 @@ fn serialize_jsx_identifier(
|
|||
node: &Ident,
|
||||
parent: NodeRef,
|
||||
) -> NodeRef {
|
||||
let raw = ctx.header(AstNode::JSXIdentifier, parent, &node.span);
|
||||
let name_pos = ctx.str_field(AstProp::Name);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
ctx.write_str(name_pos, &node.sym);
|
||||
|
||||
pos
|
||||
let pos = ctx.alloc_jsx_identifier(parent, &node.span);
|
||||
ctx.write_jsx_identifier(pos, &node.sym)
|
||||
}
|
||||
|
||||
fn serialize_pat(
|
||||
|
@ -2536,10 +2332,7 @@ fn serialize_prop_name(
|
|||
serialize_ident_name(ctx, ident_name, parent)
|
||||
}
|
||||
PropName::Str(str_prop) => {
|
||||
let raw = ctx.header(AstNode::StringLiteral, parent, &str_prop.span);
|
||||
let value_pos = ctx.str_field(AstProp::Value);
|
||||
ctx.write_str(value_pos, &str_prop.value);
|
||||
ctx.commit_schema(raw)
|
||||
serialize_lit(ctx, &Lit::Str(str_prop.clone()), parent)
|
||||
}
|
||||
PropName::Num(number) => {
|
||||
serialize_lit(ctx, &Lit::Num(number.clone()), parent)
|
||||
|
@ -2558,54 +2351,105 @@ fn serialize_lit(
|
|||
) -> NodeRef {
|
||||
match lit {
|
||||
Lit::Str(node) => {
|
||||
let raw = ctx.header(AstNode::StringLiteral, parent, &node.span);
|
||||
let raw = ctx.header(AstNode::Literal, parent, &node.span);
|
||||
let value_pos = ctx.str_field(AstProp::Value);
|
||||
let raw_pos = ctx.str_field(AstProp::Raw);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
let raw_value = if let Some(v) = &node.raw {
|
||||
v.to_string()
|
||||
} else {
|
||||
format!("{}", node.value).to_string()
|
||||
};
|
||||
|
||||
ctx.write_str(value_pos, &node.value);
|
||||
ctx.write_str(raw_pos, &raw_value);
|
||||
|
||||
pos
|
||||
}
|
||||
Lit::Bool(lit_bool) => {
|
||||
let raw = ctx.header(AstNode::Bool, parent, &lit_bool.span);
|
||||
Lit::Bool(node) => {
|
||||
let raw = ctx.header(AstNode::Literal, parent, &node.span);
|
||||
let value_pos = ctx.bool_field(AstProp::Value);
|
||||
let raw_pos = ctx.str_field(AstProp::Raw);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
ctx.write_bool(value_pos, lit_bool.value);
|
||||
ctx.write_bool(value_pos, node.value);
|
||||
ctx.write_str(raw_pos, &format!("{}", node.value));
|
||||
|
||||
pos
|
||||
}
|
||||
Lit::Null(node) => {
|
||||
let raw = ctx.header(AstNode::Null, parent, &node.span);
|
||||
ctx.commit_schema(raw)
|
||||
}
|
||||
Lit::Num(node) => {
|
||||
let raw = ctx.header(AstNode::NumericLiteral, parent, &node.span);
|
||||
let value_pos = ctx.str_field(AstProp::Value);
|
||||
let raw = ctx.header(AstNode::Literal, parent, &node.span);
|
||||
ctx.null_field(AstProp::Value);
|
||||
let raw_pos = ctx.str_field(AstProp::Raw);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
ctx.write_str(raw_pos, "null");
|
||||
|
||||
pos
|
||||
}
|
||||
Lit::Num(node) => {
|
||||
let raw = ctx.header(AstNode::Literal, parent, &node.span);
|
||||
let value_pos = ctx.num_field(AstProp::Value);
|
||||
let raw_pos = ctx.str_field(AstProp::Raw);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
let raw_value = if let Some(v) = &node.raw {
|
||||
v.to_string()
|
||||
} else {
|
||||
format!("{}", node.value).to_string()
|
||||
};
|
||||
|
||||
let value = node.raw.as_ref().unwrap();
|
||||
ctx.write_str(value_pos, value);
|
||||
ctx.write_num(value_pos, value);
|
||||
ctx.write_str(raw_pos, &raw_value);
|
||||
|
||||
pos
|
||||
}
|
||||
Lit::BigInt(node) => {
|
||||
let raw = ctx.header(AstNode::BigIntLiteral, parent, &node.span);
|
||||
let raw = ctx.header(AstNode::Literal, parent, &node.span);
|
||||
let value_pos = ctx.str_field(AstProp::Value);
|
||||
let raw_pos = ctx.str_field(AstProp::Raw);
|
||||
let bigint_pos = ctx.str_field(AstProp::BigInt);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
let raw_bigint_value = if let Some(v) = &node.raw {
|
||||
let mut s = v.to_string();
|
||||
s.pop();
|
||||
s.to_string()
|
||||
} else {
|
||||
format!("{}", node.value).to_string()
|
||||
};
|
||||
|
||||
let raw_value = if let Some(v) = &node.raw {
|
||||
v.to_string()
|
||||
} else {
|
||||
format!("{}", node.value).to_string()
|
||||
};
|
||||
|
||||
// FIXME
|
||||
|
||||
ctx.write_str(value_pos, &node.value.to_string());
|
||||
ctx.write_str(bigint_pos, &raw_bigint_value);
|
||||
ctx.write_str(raw_pos, &raw_value);
|
||||
|
||||
pos
|
||||
}
|
||||
Lit::Regex(node) => {
|
||||
let raw = ctx.header(AstNode::RegExpLiteral, parent, &node.span);
|
||||
let pattern_pos = ctx.str_field(AstProp::Pattern);
|
||||
let raw = ctx.header(AstNode::Literal, parent, &node.span);
|
||||
let _obj_pos = ctx.obj_field(AstProp::Regex, 2);
|
||||
let flags_pos = ctx.str_field(AstProp::Flags);
|
||||
let pattern_pos = ctx.str_field(AstProp::Pattern);
|
||||
let raw_pos = ctx.str_field(AstProp::Raw);
|
||||
let value_pos = ctx.regex_field(AstProp::Value);
|
||||
let pos = ctx.commit_schema(raw);
|
||||
|
||||
let raw = format!("/{}/{}", node.exp.as_str(), node.flags.as_str());
|
||||
|
||||
ctx.write_str(pattern_pos, node.exp.as_str());
|
||||
ctx.write_str(flags_pos, node.flags.as_str());
|
||||
ctx.write_str(raw_pos, &raw);
|
||||
ctx.write_regex(value_pos, &raw);
|
||||
|
||||
pos
|
||||
}
|
||||
|
@ -3024,6 +2868,9 @@ fn extract_pos(pos: NodePos) -> usize {
|
|||
NodePos::Str(str_pos) => str_pos.0,
|
||||
NodePos::Undef(undef_pos) => undef_pos.0,
|
||||
NodePos::Null(null_pos) => null_pos.0,
|
||||
NodePos::Num(num_pos) => num_pos.0,
|
||||
NodePos::Obj(obj_pos) => obj_pos.0,
|
||||
NodePos::Regex(reg_pos) => reg_pos.0,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
2
test_lint_plugins/.vscode/settings.json
vendored
2
test_lint_plugins/.vscode/settings.json
vendored
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"deno.path": "/Users/ib/dev/deno/target/debug/deno"
|
||||
"deno.path": "/Users/marvinh/dev/denoland/deno/target/debug/deno"
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"rules": {
|
||||
"exclude": [
|
||||
"ban-ts-comment",
|
||||
"prefix/whatever"
|
||||
"test-plugin-local/first-rule"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
99
tests/unit/__snapshots__/lint_plugin_test.ts.snap
Normal file
99
tests/unit/__snapshots__/lint_plugin_test.ts.snap
Normal file
|
@ -0,0 +1,99 @@
|
|||
export const snapshot = {};
|
||||
|
||||
snapshot[`Plugin - Literal 1`] = `
|
||||
{
|
||||
range: [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
raw: "1",
|
||||
type: "Literal",
|
||||
value: 1,
|
||||
}
|
||||
`;
|
||||
|
||||
snapshot[`Plugin - Literal 2`] = `
|
||||
{
|
||||
range: [
|
||||
1,
|
||||
6,
|
||||
],
|
||||
raw: "'foo'",
|
||||
type: "Literal",
|
||||
value: "foo",
|
||||
}
|
||||
`;
|
||||
|
||||
snapshot[`Plugin - Literal 3`] = `
|
||||
{
|
||||
range: [
|
||||
1,
|
||||
6,
|
||||
],
|
||||
raw: '"foo"',
|
||||
type: "Literal",
|
||||
value: "foo",
|
||||
}
|
||||
`;
|
||||
|
||||
snapshot[`Plugin - Literal 4`] = `
|
||||
{
|
||||
range: [
|
||||
1,
|
||||
5,
|
||||
],
|
||||
raw: "true",
|
||||
type: "Literal",
|
||||
value: true,
|
||||
}
|
||||
`;
|
||||
|
||||
snapshot[`Plugin - Literal 5`] = `
|
||||
{
|
||||
range: [
|
||||
1,
|
||||
6,
|
||||
],
|
||||
raw: "false",
|
||||
type: "Literal",
|
||||
value: false,
|
||||
}
|
||||
`;
|
||||
|
||||
snapshot[`Plugin - Literal 6`] = `
|
||||
{
|
||||
range: [
|
||||
1,
|
||||
5,
|
||||
],
|
||||
raw: "null",
|
||||
type: "Literal",
|
||||
value: null,
|
||||
}
|
||||
`;
|
||||
|
||||
snapshot[`Plugin - Literal 7`] = `
|
||||
{
|
||||
bigint: "1",
|
||||
range: [
|
||||
1,
|
||||
3,
|
||||
],
|
||||
raw: "1n",
|
||||
type: "Literal",
|
||||
value: "1",
|
||||
}
|
||||
`;
|
||||
|
||||
snapshot[`Plugin - Literal 8`] = `
|
||||
{
|
||||
flags: "g",
|
||||
pattern: "foo",
|
||||
range: [
|
||||
1,
|
||||
7,
|
||||
],
|
||||
raw: "/foo/g",
|
||||
type: "Literal",
|
||||
}
|
||||
`;
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
import { assertEquals } from "./test_util.ts";
|
||||
import { assertSnapshot } from "@std/testing/snapshot";
|
||||
|
||||
// TODO(@marvinhagemeister) Remove once we land "official" types
|
||||
export interface LintReportData {
|
||||
|
@ -103,6 +104,8 @@ function testLintNode(source: string, ...selectors: string[]) {
|
|||
},
|
||||
});
|
||||
|
||||
assertEquals(log.length > 0, true);
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
|
@ -323,292 +326,85 @@ Deno.test("Plugin - Program", () => {
|
|||
});
|
||||
});
|
||||
|
||||
Deno.test("Plugin - BlockStatement", () => {
|
||||
Deno.test("Plugin - BlockStatement", async (t) => {
|
||||
const node = testLintNode("{ foo; }", "BlockStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "BlockStatement",
|
||||
range: [1, 9],
|
||||
body: [{
|
||||
type: "ExpressionStatement",
|
||||
range: [3, 7],
|
||||
expression: {
|
||||
type: "Identifier",
|
||||
name: "foo",
|
||||
range: [3, 6],
|
||||
},
|
||||
}],
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - BreakStatement", () => {
|
||||
Deno.test("Plugin - BreakStatement", async (t) => {
|
||||
let node = testLintNode("break;", "BreakStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "BreakStatement",
|
||||
range: [1, 7],
|
||||
label: null,
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("break foo;", "BreakStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "BreakStatement",
|
||||
range: [1, 11],
|
||||
label: {
|
||||
type: "Identifier",
|
||||
range: [7, 10],
|
||||
name: "foo",
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ContinueStatement", () => {
|
||||
Deno.test("Plugin - ContinueStatement", async (t) => {
|
||||
let node = testLintNode("continue;", "ContinueStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ContinueStatement",
|
||||
range: [1, 10],
|
||||
label: null,
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("continue foo;", "ContinueStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ContinueStatement",
|
||||
range: [1, 14],
|
||||
label: {
|
||||
type: "Identifier",
|
||||
range: [10, 13],
|
||||
name: "foo",
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - DebuggerStatement", () => {
|
||||
Deno.test("Plugin - DebuggerStatement", async (t) => {
|
||||
const node = testLintNode("debugger;", "DebuggerStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "DebuggerStatement",
|
||||
range: [1, 10],
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - DoWhileStatement", () => {
|
||||
Deno.test("Plugin - DoWhileStatement", async (t) => {
|
||||
const node = testLintNode("do {} while (foo);", "DoWhileStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "DoWhileStatement",
|
||||
range: [1, 19],
|
||||
test: {
|
||||
type: "Identifier",
|
||||
range: [14, 17],
|
||||
name: "foo",
|
||||
},
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
range: [4, 6],
|
||||
body: [],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ExpressionStatement", () => {
|
||||
Deno.test("Plugin - ExpressionStatement", async (t) => {
|
||||
const node = testLintNode("foo;", "ExpressionStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ExpressionStatement",
|
||||
range: [1, 5],
|
||||
expression: {
|
||||
type: "Identifier",
|
||||
range: [1, 4],
|
||||
name: "foo",
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ForInStatement", () => {
|
||||
Deno.test("Plugin - ForInStatement", async (t) => {
|
||||
const node = testLintNode("for (a in b) {}", "ForInStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ForInStatement",
|
||||
range: [1, 16],
|
||||
left: {
|
||||
type: "Identifier",
|
||||
range: [6, 7],
|
||||
name: "a",
|
||||
},
|
||||
right: {
|
||||
type: "Identifier",
|
||||
range: [11, 12],
|
||||
name: "b",
|
||||
},
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
range: [14, 16],
|
||||
body: [],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ForOfStatement", () => {
|
||||
Deno.test("Plugin - ForOfStatement", async (t) => {
|
||||
let node = testLintNode("for (a of b) {}", "ForOfStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ForOfStatement",
|
||||
range: [1, 16],
|
||||
await: false,
|
||||
left: {
|
||||
type: "Identifier",
|
||||
range: [6, 7],
|
||||
name: "a",
|
||||
},
|
||||
right: {
|
||||
type: "Identifier",
|
||||
range: [11, 12],
|
||||
name: "b",
|
||||
},
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
range: [14, 16],
|
||||
body: [],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("for await (a of b) {}", "ForOfStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ForOfStatement",
|
||||
range: [1, 22],
|
||||
await: true,
|
||||
left: {
|
||||
type: "Identifier",
|
||||
range: [12, 13],
|
||||
name: "a",
|
||||
},
|
||||
right: {
|
||||
type: "Identifier",
|
||||
range: [17, 18],
|
||||
name: "b",
|
||||
},
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
range: [20, 22],
|
||||
body: [],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ForStatement", () => {
|
||||
Deno.test("Plugin - ForStatement", async (t) => {
|
||||
let node = testLintNode("for (;;) {}", "ForStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ForStatement",
|
||||
range: [1, 12],
|
||||
init: null,
|
||||
test: null,
|
||||
update: null,
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
range: [10, 12],
|
||||
body: [],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("for (a; b; c) {}", "ForStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ForStatement",
|
||||
range: [1, 17],
|
||||
init: {
|
||||
type: "Identifier",
|
||||
range: [6, 7],
|
||||
name: "a",
|
||||
},
|
||||
test: {
|
||||
type: "Identifier",
|
||||
range: [9, 10],
|
||||
name: "b",
|
||||
},
|
||||
update: {
|
||||
type: "Identifier",
|
||||
range: [12, 13],
|
||||
name: "c",
|
||||
},
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
range: [15, 17],
|
||||
body: [],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - IfStatement", () => {
|
||||
Deno.test("Plugin - IfStatement", async (t) => {
|
||||
let node = testLintNode("if (foo) {}", "IfStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "IfStatement",
|
||||
range: [1, 12],
|
||||
test: {
|
||||
type: "Identifier",
|
||||
name: "foo",
|
||||
range: [5, 8],
|
||||
},
|
||||
consequent: {
|
||||
type: "BlockStatement",
|
||||
range: [10, 12],
|
||||
body: [],
|
||||
},
|
||||
alternate: null,
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("if (foo) {} else {}", "IfStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "IfStatement",
|
||||
range: [1, 20],
|
||||
test: {
|
||||
type: "Identifier",
|
||||
name: "foo",
|
||||
range: [5, 8],
|
||||
},
|
||||
consequent: {
|
||||
type: "BlockStatement",
|
||||
range: [10, 12],
|
||||
body: [],
|
||||
},
|
||||
alternate: {
|
||||
type: "BlockStatement",
|
||||
range: [18, 20],
|
||||
body: [],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - LabeledStatement", () => {
|
||||
Deno.test("Plugin - LabeledStatement", async (t) => {
|
||||
const node = testLintNode("foo: {};", "LabeledStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "LabeledStatement",
|
||||
range: [1, 8],
|
||||
label: {
|
||||
type: "Identifier",
|
||||
name: "foo",
|
||||
range: [1, 4],
|
||||
},
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
range: [6, 8],
|
||||
body: [],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ReturnStatement", () => {
|
||||
Deno.test("Plugin - ReturnStatement", async (t) => {
|
||||
let node = testLintNode("return", "ReturnStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ReturnStatement",
|
||||
range: [1, 7],
|
||||
argument: null,
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("return foo;", "ReturnStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ReturnStatement",
|
||||
range: [1, 12],
|
||||
argument: {
|
||||
type: "Identifier",
|
||||
name: "foo",
|
||||
range: [8, 11],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - SwitchStatement", () => {
|
||||
Deno.test("Plugin - SwitchStatement", async (t) => {
|
||||
const node = testLintNode(
|
||||
`switch (foo) {
|
||||
case foo:
|
||||
|
@ -619,151 +415,388 @@ Deno.test("Plugin - SwitchStatement", () => {
|
|||
}`,
|
||||
"SwitchStatement",
|
||||
);
|
||||
assertEquals(node[0], {
|
||||
type: "SwitchStatement",
|
||||
range: [1, 94],
|
||||
discriminant: {
|
||||
type: "Identifier",
|
||||
range: [9, 12],
|
||||
name: "foo",
|
||||
},
|
||||
cases: [
|
||||
{
|
||||
type: "SwitchCase",
|
||||
range: [22, 31],
|
||||
test: {
|
||||
type: "Identifier",
|
||||
range: [27, 30],
|
||||
name: "foo",
|
||||
},
|
||||
consequent: [],
|
||||
},
|
||||
{
|
||||
type: "SwitchCase",
|
||||
range: [38, 62],
|
||||
test: {
|
||||
type: "Identifier",
|
||||
range: [43, 46],
|
||||
name: "bar",
|
||||
},
|
||||
consequent: [
|
||||
{
|
||||
type: "BreakStatement",
|
||||
label: null,
|
||||
range: [56, 62],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "SwitchCase",
|
||||
range: [69, 88],
|
||||
test: null,
|
||||
consequent: [
|
||||
{
|
||||
type: "BlockStatement",
|
||||
range: [86, 88],
|
||||
body: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ThrowStatement", () => {
|
||||
Deno.test("Plugin - ThrowStatement", async (t) => {
|
||||
const node = testLintNode("throw foo;", "ThrowStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "ThrowStatement",
|
||||
range: [1, 11],
|
||||
argument: {
|
||||
type: "Identifier",
|
||||
range: [7, 10],
|
||||
name: "foo",
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - TryStatement", () => {
|
||||
Deno.test("Plugin - TryStatement", async (t) => {
|
||||
let node = testLintNode("try {} catch {};", "TryStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "TryStatement",
|
||||
range: [1, 16],
|
||||
block: {
|
||||
type: "BlockStatement",
|
||||
range: [5, 7],
|
||||
body: [],
|
||||
},
|
||||
handler: {
|
||||
type: "CatchClause",
|
||||
range: [8, 16],
|
||||
param: null,
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
range: [14, 16],
|
||||
body: [],
|
||||
},
|
||||
},
|
||||
finalizer: null,
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("try {} catch (e) {};", "TryStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "TryStatement",
|
||||
range: [1, 20],
|
||||
block: {
|
||||
type: "BlockStatement",
|
||||
range: [5, 7],
|
||||
body: [],
|
||||
},
|
||||
handler: {
|
||||
type: "CatchClause",
|
||||
range: [8, 20],
|
||||
param: {
|
||||
type: "Identifier",
|
||||
range: [15, 16],
|
||||
name: "e",
|
||||
},
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
range: [18, 20],
|
||||
body: [],
|
||||
},
|
||||
},
|
||||
finalizer: null,
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("try {} finally {};", "TryStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "TryStatement",
|
||||
range: [1, 18],
|
||||
block: {
|
||||
type: "BlockStatement",
|
||||
range: [5, 7],
|
||||
body: [],
|
||||
},
|
||||
handler: null,
|
||||
finalizer: {
|
||||
type: "BlockStatement",
|
||||
range: [16, 18],
|
||||
body: [],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - WhileStatement", () => {
|
||||
Deno.test("Plugin - WhileStatement", async (t) => {
|
||||
const node = testLintNode("while (foo) {}", "WhileStatement");
|
||||
assertEquals(node[0], {
|
||||
type: "WhileStatement",
|
||||
range: [1, 15],
|
||||
test: {
|
||||
type: "Identifier",
|
||||
range: [8, 11],
|
||||
name: "foo",
|
||||
},
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
range: [13, 15],
|
||||
body: [],
|
||||
},
|
||||
});
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - WithStatement", async (t) => {
|
||||
const node = testLintNode("with ([]) {}", "WithStatement");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ArrayExpression", async (t) => {
|
||||
const node = testLintNode("[[],,[]]", "ArrayExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ArrowFunctionExpression", async (t) => {
|
||||
let node = testLintNode("() => {}", "ArrowFunctionExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("async () => {}", "ArrowFunctionExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode(
|
||||
"(a: number, ...b: any[]): any => {}",
|
||||
"ArrowFunctionExpression",
|
||||
);
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - AssignmentExpression", async (t) => {
|
||||
let node = testLintNode("a = b", "AssignmentExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = a ??= b", "AssignmentExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - AwaitExpression", async (t) => {
|
||||
const node = testLintNode("await foo;", "AwaitExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - BinaryExpression", async (t) => {
|
||||
let node = testLintNode("a > b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a >= b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a < b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a <= b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a == b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a === b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a != b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a !== b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a << b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a >> b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a >>> b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a + b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a - b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a * b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a / b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a % b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a | b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a ^ b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a & b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a in b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a ** b", "BinaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - CallExpression", async (t) => {
|
||||
let node = testLintNode("foo();", "CallExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("foo(a, ...b);", "CallExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("foo?.();", "CallExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ChainExpression", async (t) => {
|
||||
const node = testLintNode("a?.b", "ChainExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ClassExpression", async (t) => {
|
||||
let node = testLintNode("a = class {}", "ClassExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = class Foo {}", "ClassExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = class Foo extends Bar {}", "ClassExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode(
|
||||
"a = class Foo extends Bar implements Baz, Baz2 {}",
|
||||
"ClassExpression",
|
||||
);
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = class Foo<T> {}", "ClassExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = class { foo() {} }", "ClassExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = class { #foo() {} }", "ClassExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = class { foo: number }", "ClassExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = class { foo = bar }", "ClassExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode(
|
||||
"a = class { constructor(public foo: string) {} }",
|
||||
"ClassExpression",
|
||||
);
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = class { #foo: number = bar }", "ClassExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = class { static foo = bar }", "ClassExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode(
|
||||
"a = class { static foo; static { foo = bar } }",
|
||||
"ClassExpression",
|
||||
);
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ConditionalExpression", async (t) => {
|
||||
const node = testLintNode("a ? b : c", "ConditionalExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - FunctionExpression", async (t) => {
|
||||
let node = testLintNode("a = function () {}", "FunctionExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = function foo() {}", "FunctionExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode(
|
||||
"a = function (a?: number, ...b: any[]): any {}",
|
||||
"FunctionExpression",
|
||||
);
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a = async function* () {}", "FunctionExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - Identifier", async (t) => {
|
||||
const node = testLintNode("a", "Identifier");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ImportExpression", async (t) => {
|
||||
const node = testLintNode(
|
||||
"import('foo', { with: { type: 'json' }}",
|
||||
"ImportExpression",
|
||||
);
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - LogicalExpression", async (t) => {
|
||||
let node = testLintNode("a && b", "LogicalExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a || b", "LogicalExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a ?? b", "LogicalExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - MemberExpression", async (t) => {
|
||||
let node = testLintNode("a.b", "MemberExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a['b']", "MemberExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - MetaProp", async (t) => {
|
||||
const node = testLintNode("import.meta", "MetaProp");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - NewExpression", async (t) => {
|
||||
let node = testLintNode("new Foo()", "NewExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("new Foo(a?: any, ...b: any[])", "NewExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ObjectExpression", async (t) => {
|
||||
let node = testLintNode("{}", "ObjectExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("{ a, b: c, [c]: d }", "ObjectExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - PrivateIdentifier", async (t) => {
|
||||
const node = testLintNode("class Foo { #foo = foo }", "PrivateIdentifier");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - SequenceExpression", async (t) => {
|
||||
const node = testLintNode("(a, b)", "SequenceExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - Super", async (t) => {
|
||||
const node = testLintNode(
|
||||
"class Foo extends Bar { constructor() { super(); } }",
|
||||
"Super",
|
||||
);
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - TaggedTemplateExpression", async (t) => {
|
||||
const node = testLintNode(
|
||||
"foo`foo ${bar} baz`",
|
||||
"TaggedTemplateExpression",
|
||||
);
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - TemplateLiteral", async (t) => {
|
||||
const node = testLintNode(
|
||||
"`foo ${bar} baz`",
|
||||
"TemplateLiteral",
|
||||
);
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - ThisExpression", async (t) => {
|
||||
const node = testLintNode("this", "ThisExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - TSAsExpression", async (t) => {
|
||||
let node = testLintNode("a as b", "TSAsExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a as const", "TSAsExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - TSNonNullExpression", async (t) => {
|
||||
const node = testLintNode("a!", "TSNonNullExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - TSSatisfiesExpression", async (t) => {
|
||||
const node = testLintNode("a satisfies b", "TSSatisfiesExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - UnaryExpression", async (t) => {
|
||||
let node = testLintNode("typeof a", "UnaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("void 0", "UnaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("-a", "UnaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("+a", "UnaryExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - UpdateExpression", async (t) => {
|
||||
let node = testLintNode("a++", "UpdateExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("++a", "UpdateExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("a--", "UpdateExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("--a", "UpdateExpression");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test("Plugin - YieldExpression", async (t) => {
|
||||
const node = testLintNode(
|
||||
"function* foo() { yield bar; }",
|
||||
"YieldExpression",
|
||||
);
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
||||
Deno.test.only("Plugin - Literal", async (t) => {
|
||||
let node = testLintNode("1", "Literal");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("'foo'", "Literal");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode('"foo"', "Literal");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("true", "Literal");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("false", "Literal");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("null", "Literal");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("1n", "Literal");
|
||||
await assertSnapshot(t, node[0]);
|
||||
|
||||
node = testLintNode("/foo/g", "Literal");
|
||||
await assertSnapshot(t, node[0]);
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue