1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 13:00:36 -05:00
This commit is contained in:
Marvin Hagemeister 2024-12-10 05:34:12 +01:00
parent 280d10e801
commit 99b9e726d4
4 changed files with 209 additions and 74 deletions

View file

@ -181,7 +181,7 @@ const AstType = {
// Custom
EmptyExpr: 84,
Spread: 85,
ObjProperty: 86,
Property: 86,
VarDeclarator: 87,
CatchClause: 88,
@ -1000,7 +1000,7 @@ class ArrowFunctionExpression extends BaseNode {
}
/** @implements {Deno.AssignmentExpression} */
class AssignmentExpression {
class AssignmentExpression extends BaseNode {
type = /** @type {const} */ ("AssignmentExpression");
range;
get left() {
@ -1024,12 +1024,15 @@ class AssignmentExpression {
/**
* @param {AstContext} ctx
* @param {number} parentId
* @param {Deno.Range} range
* @param {number} flags
* @param {number} leftId
* @param {number} rightId
*/
constructor(ctx, range, flags, leftId, rightId) {
constructor(ctx, parentId, range, flags, leftId, rightId) {
super(ctx, parentId);
this.#ctx = ctx;
this.#leftId = leftId;
this.#rightId = rightId;
@ -1045,37 +1048,37 @@ class AssignmentExpression {
function getAssignOperator(n) {
switch (n) {
case 0:
return "&&=";
return "=";
case 1:
return "&=";
return "+=";
case 2:
return "**=";
return "-=";
case 3:
return "*=";
case 4:
return "||=";
case 5:
return "|=";
case 6:
return "^=";
case 7:
return "=";
case 8:
return ">>=";
case 9:
return ">>>=";
case 10:
return "<<=";
case 11:
return "-=";
case 12:
return "%=";
case 13:
return "+=";
case 14:
return "??=";
case 15:
return "/=";
case 5:
return "%=";
case 6:
return "<<=";
case 7:
return ">>=";
case 8:
return ">>>=";
case 9:
return "|=";
case 10:
return "^=";
case 11:
return "&=";
case 12:
return "**=";
case 13:
return "&&=";
case 14:
return "||=";
case 15:
return "??=";
default:
throw new Error(`Unknown operator: ${n}`);
}
@ -1505,6 +1508,32 @@ class NewExpression {
}
}
/** @implements {Deno.ObjectExpression} */
class ObjectExpression extends BaseNode {
type = /** @type {const} */ ("ObjectExpression");
range;
get properties() {
return createChildNodes(this.#ctx, this.#elemIds);
}
#ctx;
#elemIds;
/**
* @param {AstContext} ctx
* @param {number} parentId
* @param {Deno.Range} range
* @param {number[]} elemIds
*/
constructor(ctx, parentId, range, elemIds) {
super(ctx, parentId);
this.#ctx = ctx;
this.range = range;
this.#elemIds = elemIds;
}
}
/** @implements {Deno.ParenthesisExpression} */
class ParenthesisExpression extends BaseNode {
type = /** @type {const} */ ("ParenthesisExpression");
@ -1553,6 +1582,48 @@ class PrivateIdentifier extends BaseNode {
}
}
/** @implements {Deno.Property} */
class Property extends BaseNode {
type = /** @type {const} */ ("Property");
range;
#ctx;
get key() {
return /** @type {*} */ (createAstNode(this.#ctx, this.#keyId));
}
get value() {
return /** @type {*} */ (createAstNode(this.#ctx, this.#valueId));
}
#keyId;
#valueId;
// FIXME
computed = false;
method = false;
shorthand = false;
kind = /** @type {const} */ ("get");
/**
* @param {AstContext} ctx
* @param {number} parentId
* @param {Deno.Range} range
* @param {number} keyId
* @param {number} valueId
*/
constructor(ctx, parentId, range, keyId, valueId) {
super(ctx, parentId);
// FIXME flags
this.#ctx = ctx;
this.range = range;
this.#keyId = keyId;
this.#valueId = valueId;
}
}
/** @implements {Deno.SequenceExpression} */
class SequenceExpression extends BaseNode {
type = /** @type {const} */ ("SequenceExpression");
@ -2120,7 +2191,6 @@ const DECODER = new TextDecoder();
* buf: Uint8Array,
* strTable: Map<number, string>,
* idTable: number[],
* visited: Set<number>,
* }} AstContext
*/
@ -2329,8 +2399,19 @@ function createAstNode(ctx, id) {
returnTypeId,
);
}
case AstType.AssignmentExpression:
throw new AssignmentExpression(ctx, range, flags, 0, 0); // FIXME
case AstType.AssignmentExpression: {
const flags = buf[offset];
const leftId = readU32(buf, offset + 1);
const rightId = readU32(buf, offset + 5);
return new AssignmentExpression(
ctx,
parentId,
range,
flags,
leftId,
rightId,
);
}
case AstType.AwaitExpression:
throw new AwaitExpression(ctx, range, 0); // FIXME
case AstType.BinaryExpression:
@ -2372,8 +2453,10 @@ function createAstNode(ctx, id) {
throw new MetaProperty(ctx, range, 0, 0); // FIXME
case AstType.NewExpression:
throw new NewExpression(ctx, range, 0); // FIXME
case AstType.ObjectExpression:
throw new Error("TODO");
case AstType.ObjectExpression: {
const elemIds = readChildIds(buf, offset);
return new ObjectExpression(ctx, parentId, range, elemIds);
}
case AstType.ParenthesisExpression: {
const exprId = readU32(buf, offset);
return new ParenthesisExpression(ctx, parentId, range, exprId);
@ -2382,6 +2465,12 @@ function createAstNode(ctx, id) {
const strId = readU32(buf, offset);
return new PrivateIdentifier(ctx, parentId, range, strId);
}
case AstType.Property: {
const flags = buf[offset]; // FIXME
const keyId = readU32(buf, offset + 1);
const valueId = readU32(buf, offset + 5);
return new Property(ctx, parentId, range, keyId, valueId);
}
case AstType.StaticBlock:
throw new Error("TODO");
case AstType.SequenceExpression: {
@ -2511,7 +2600,7 @@ function createAstContext(buf) {
}
/** @type {AstContext} */
const ctx = { buf, idTable, strTable, visited: new Set() };
const ctx = { buf, idTable, strTable };
return ctx;
}
@ -2618,16 +2707,11 @@ function traverseInner(ctx, visitTypes, visitor, id) {
// Empty id
if (id === 0) return;
const { idTable, buf, visited } = ctx;
const { idTable, buf } = ctx;
if (id >= idTable.length) {
throw new Error(`Invalid node id: ${id}`);
}
if (visited.has(id)) {
throw new Error(`Already visited ${id}`);
}
visited.add(id);
let offset = idTable[id];
if (offset === undefined) throw new Error(`Unknown id: ${id}`);
@ -2655,6 +2739,7 @@ function traverseInner(ctx, visitTypes, visitor, id) {
// Multiple children only
case AstType.ArrayExpression:
case AstType.BlockStatement:
case AstType.ObjectExpression:
case AstType.SequenceExpression: {
const stmtsIds = readChildIds(buf, offset);
return traverseChildren(ctx, visitTypes, visitor, stmtsIds);
@ -2708,8 +2793,33 @@ function traverseInner(ctx, visitTypes, visitor, id) {
return;
}
case AstType.AssignmentExpression: {
// Skip flags
offset += 1;
const leftId = readU32(buf, offset);
const rightId = readU32(buf, offset + 4);
traverseInner(ctx, visitTypes, visitor, leftId);
traverseInner(ctx, visitTypes, visitor, rightId);
return;
}
case AstType.Property: {
// Skip flags
offset += 1;
const keyId = readU32(buf, offset);
const valueId = readU32(buf, offset + 4);
traverseInner(ctx, visitTypes, visitor, keyId);
traverseInner(ctx, visitTypes, visitor, valueId);
return;
}
// Two children
case AstType.AssignmentPattern:
case AstType.LabeledStatement:
case AstType.WhileStatement: {
const firstId = readU32(buf, offset);

View file

@ -1,13 +1,14 @@
use deno_ast::{
swc::{
ast::{
AssignTarget, BlockStmtOrExpr, Callee, Decl, Expr, ForHead, Ident, Lit,
MemberProp, ModuleDecl, ModuleItem, Pat, Program, Prop, PropName,
PropOrSpread, SimpleAssignTarget, Stmt, SuperProp, TsType, VarDeclOrExpr,
AssignTarget, BlockStmtOrExpr, Callee, Decl, Expr, FnExpr, ForHead,
Ident, Lit, MemberProp, ModuleDecl, ModuleItem, Pat, Program, Prop,
PropName, PropOrSpread, SimpleAssignTarget, Stmt, SuperProp, TsType,
VarDeclOrExpr,
},
common::{Span, Spanned, DUMMY_SP},
},
view::BinaryOp,
view::{AssignOp, BinaryOp},
ParsedSource,
};
use indexmap::IndexMap;
@ -180,6 +181,27 @@ enum Flag {
PropSetter,
}
fn assign_op_to_flag(m: AssignOp) -> u8 {
match m {
AssignOp::Assign => 0,
AssignOp::AddAssign => 1,
AssignOp::SubAssign => 2,
AssignOp::MulAssign => 3,
AssignOp::DivAssign => 4,
AssignOp::ModAssign => 5,
AssignOp::LShiftAssign => 6,
AssignOp::RShiftAssign => 7,
AssignOp::ZeroFillRShiftAssign => 8,
AssignOp::BitOrAssign => 9,
AssignOp::BitXorAssign => 10,
AssignOp::BitAndAssign => 11,
AssignOp::ExpAssign => 12,
AssignOp::AndAssign => 13,
AssignOp::OrAssign => 14,
AssignOp::NullishAssign => 15,
}
}
impl From<Flag> for u8 {
fn from(m: Flag) -> u8 {
match m {
@ -324,6 +346,8 @@ pub fn serialize_ast_bin(parsed_source: &ParsedSource) -> Vec<u8> {
let program = &parsed_source.program();
let mut flags = FlagValue::new();
eprintln!("SWC {:#?}", program);
match program.as_ref() {
Program::Module(module) => {
let id = ctx.push_node(AstNode::Program, parent_id, &module.span);
@ -697,17 +721,7 @@ fn serialize_decl(
let child_offset = ctx.reserve_child_ids(2); // Name + init
let decl_id = match &decl.name {
Pat::Ident(binding_ident) => {
serialize_ident(ctx, &binding_ident.id, child_id)
}
Pat::Array(array_pat) => todo!(),
Pat::Rest(rest_pat) => todo!(),
Pat::Object(object_pat) => todo!(),
Pat::Assign(assign_pat) => todo!(),
Pat::Invalid(invalid) => todo!(),
Pat::Expr(expr) => serialize_expr(ctx, expr.as_ref(), child_id),
};
let decl_id = serialize_pat(ctx, &decl.name, child_id);
ctx.set_child(child_offset, decl_id, 0);
if let Some(init) = &decl.init {
@ -800,7 +814,6 @@ fn serialize_expr(
}
Expr::Object(node) => {
let id = ctx.push_node(AstNode::Object, parent_id, &node.span);
let offset = ctx.reserve_child_ids_with_count(node.props.len());
for (i, prop) in node.props.iter().enumerate() {
@ -828,12 +841,6 @@ fn serialize_expr(
let child_offset = ctx.reserve_child_ids(2);
// FIXME: optional
// computed: boolean;
// key: PropertyName;
// kind: 'get' | 'init' | 'set';
// method: boolean;
// optional: boolean;
// shorthand: boolean;
match prop.as_ref() {
Prop::Shorthand(ident) => {
flags.set(Flag::PropShorthand);
@ -856,15 +863,23 @@ fn serialize_expr(
ctx.set_child(child_offset, value_id, 1);
}
Prop::Assign(assign_prop) => {
let child_id =
ctx.push_node(AstNode::Assign, prop_id, &assign_prop.span);
let child_id = ctx.push_node(
AstNode::AssignmentPattern,
prop_id,
&assign_prop.span,
);
let key_id = serialize_ident(ctx, &assign_prop.key, child_id);
let offset = ctx.reserve_child_ids(2);
let key_id = serialize_ident(ctx, &assign_prop.key, prop_id);
let value_id =
serialize_expr(ctx, assign_prop.value.as_ref(), child_id);
serialize_expr(ctx, assign_prop.value.as_ref(), prop_id);
ctx.set_child(child_id, key_id, 0);
ctx.set_child(child_id, value_id, 1);
ctx.set_child(offset, key_id, 0);
ctx.set_child(offset, value_id, 1);
ctx.set_child(child_offset, key_id, 0);
ctx.set_child(child_offset, child_id, 1);
}
Prop::Getter(getter_prop) => {
flags.set(Flag::PropGetter);
@ -885,9 +900,11 @@ fn serialize_expr(
let key_id =
serialize_prop_name(ctx, &setter_prop.key, prop_id);
ctx.set_child(child_offset, key_id, 0);
// let value_id =
// ctx.push_node(AstNode::FnExpr, prop_id, &setter_prop.span);
let child_id =
ctx.push_node(AstNode::FnExpr, prop_id, &setter_prop.span);
// TODO
// if let Some(body) = &setter_prop.body {
// serialize_stmt(ctx, &Stmt::Block(body.clone()));
@ -961,6 +978,8 @@ fn serialize_expr(
}
Expr::Assign(node) => {
let id = ctx.push_node(AstNode::Assign, parent_id, &node.span);
ctx.result.push(assign_op_to_flag(node.op));
let offset = ctx.reserve_child_ids(2);
let left_id = match &node.left {

View file

@ -6283,7 +6283,7 @@ declare namespace Deno {
arguments: Array<Expression | SpreadElement>;
optional: boolean; // FIXME only in TSEstree
// FIXME
typeArguments: null; // FIXME
typeArguments: any; // FIXME
}
export interface ChainExpression extends BaseNode {
@ -6965,6 +6965,7 @@ declare namespace Deno {
| Statement
| CatchClause
| PrivateIdentifier
| Property
| JSXNode;
export interface LintRuleContext {

View file

@ -24,7 +24,12 @@ a = {
get foo() {
return 1;
},
set foo(a) {
2;
},
// FIXME
// set foo(a) {
// 2;
// },
// bar() {},
// async barAsync() {},
// *barGen() {},
// async *barAsyncGen() {},
};