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 2025-01-06 16:36:58 +01:00
parent d773c32e0a
commit 8fc684c126
5 changed files with 159 additions and 100 deletions

View file

@ -19,7 +19,14 @@ const {
// Keep these in sync with Rust
const AST_IDX_INVALID = 0;
const AST_GROUP_TYPE = 1;
const NODE_SIZE = 1 + 4 + 4 + 4;
/// <type u8>
/// <prop offset u32>
/// <child idx u32>
/// <next idx u32>
/// <parent idx u32>
const NODE_SIZE = 1 + 4 + 4 + 4 + 4;
// Span size in buffer: u32 + u32
const SPAN_SIZE = 4 + 4;
// Keep in sync with Rust
// These types are expected to be present on every node. Note that this
@ -475,6 +482,44 @@ function toJsValue(ctx, idx) {
return node;
}
/**
* @param {AstContext} ctx
* @param {number} idx
* @returns {Node["range"]}
*/
function readSpan(ctx, idx) {
let offset = ctx.spansOffset + (idx * SPAN_SIZE);
const start = readU32(ctx.buf, offset);
offset += 4;
const end = readU32(ctx.buf, offset);
return [start, end];
}
/**
* @param {AstContext["buf"]} buf
* @param {number} idx
* @returns {number}
*/
function readParent(buf, idx) {
let offset = idx * NODE_SIZE;
// type + prop offset + child + next
offset += 1 + 4 + 4 + 4;
return readU32(buf, offset);
}
/**
* @param {AstContext["buf"]} buf
* @param {number} idx
* @returns {number}
*/
function readPropOffset(buf, idx) {
let offset = idx * NODE_SIZE;
// type + prop offset + child + next
offset += 1;
return readU32(buf, offset);
}
/**
* @param {AstContext["strTable"]} strTable
* @param {number} strId
@ -523,8 +568,9 @@ function readObject(ctx, offset) {
function readProperty(ctx, offset) {
const { buf } = ctx;
const kind = buf[offset + 1];
offset += 2;
const kind = buf[offset++];
// skip over name
offset++;
if (kind === PropFlags.Ref) {
const value = readU32(buf, offset);
@ -540,7 +586,8 @@ function readProperty(ctx, offset) {
}
return nodes;
} else if (kind === PropFlags.Bool) {
return buf[offset] === 1;
const v = readU32(buf, offset);
return v === 1;
} else if (kind === PropFlags.String) {
const v = readU32(buf, offset);
return getString(ctx.strTable, v);
@ -564,26 +611,27 @@ function readProperty(ctx, offset) {
/**
* Read a specific property from a node
* @param {AstContext} ctx
* @param {number} offset
* @param {number} idx
* @param {number} search
* @returns {*}
*/
function readValue(ctx, offset, search) {
function readValue(ctx, idx, search) {
const { buf } = ctx;
const type = buf[offset];
const type = buf[idx * NODE_SIZE];
if (search === AST_PROP_TYPE) {
return getString(ctx.strTable, ctx.strByType[type]);
} else if (search === AST_PROP_RANGE) {
const start = readU32(buf, offset + 1 + 4);
const end = readU32(buf, offset + 1 + 4 + 4);
return [start, end];
return readSpan(ctx, idx);
} else if (search === AST_PROP_PARENT) {
const pos = readU32(buf, offset + 1);
return getNode(ctx, pos);
const parent = readParent(buf, idx);
return getNode(ctx, parent);
}
offset = findPropOffset(ctx.buf, offset, search);
const propOffset = readPropOffset(buf, idx);
const offset = findPropOffset(ctx.buf, propOffset, search);
if (offset === -1) return undefined;
return readProperty(ctx, offset);
@ -834,7 +882,7 @@ class MatchCtx {
/**
* @param {Uint8Array} buf
* @param {AstContext} buf
* @returns {AstContext}
*/
function createAstContext(buf) {
/** @type {Map<number, string>} */
@ -842,6 +890,7 @@ function createAstContext(buf) {
// The buffer has a few offsets at the end which allows us to easily
// jump to the relevant sections of the message.
const spansOffset = readU32(buf, buf.length - 20);
const typeMapOffset = readU32(buf, buf.length - 16);
const propMapOffset = readU32(buf, buf.length - 12);
const strTableOffset = readU32(buf, buf.length - 8);
@ -904,6 +953,7 @@ function createAstContext(buf) {
buf,
strTable,
rootOffset,
spansOffset,
nodes: new Map(),
strTableOffset,
strByProp,
@ -915,8 +965,10 @@ function createAstContext(buf) {
setNodeGetters(ctx);
console.log(ctx);
// DEV ONLY: Enable this to inspect the buffer message
// _dump(ctx);
_dump(ctx);
return ctx;
}
@ -1150,38 +1202,35 @@ function _dump(ctx) {
// deno-lint-ignore no-console
console.log();
let offset = 0;
let idx = 0;
while (idx < (strTableOffset / NODE_SIZE)) {
const offset = idx * NODE_SIZE;
while (offset < strTableOffset) {
const type = buf[offset];
const name = getString(ctx.strTable, ctx.strByType[type]);
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(`${name}, offset: ${offset}, type: ${type}`);
offset += 1;
console.log(`${name}, idx: ${idx}, offset: ${offset}, type: ${type}`);
const parent = readU32(buf, offset);
offset += 4;
const parent = readParent(buf, idx);
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(` parent: ${parent}`);
const start = readU32(buf, offset);
offset += 4;
const end = readU32(buf, offset);
offset += 4;
const range = readSpan(ctx, idx);
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(` range: ${start} -> ${end}`);
console.log(` range: ${JSON.stringify(range)}`);
const count = buf[offset++];
let propOffset = readPropOffset(buf, idx);
const count = buf[propOffset++];
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(` prop count: ${count}`);
for (let i = 0; i < count; i++) {
const prop = buf[offset++];
const kind = buf[offset++];
const prop = buf[propOffset++];
const kind = buf[propOffset++];
const name = getString(ctx.strTable, ctx.strByProp[prop]);
let kindName = "unknown";
@ -1192,56 +1241,36 @@ function _dump(ctx) {
}
}
const v = readU32(buf, offset);
propOffset += 4;
if (kind === PropFlags.Ref) {
const v = readU32(buf, offset);
offset += 4;
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(` ${name}: ${v} (${kindName}, ${prop})`);
} else if (kind === PropFlags.RefArr) {
const len = readU32(buf, offset);
offset += 4;
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(` ${name}: Array(${len}) (${kindName}, ${prop})`);
for (let j = 0; j < len; j++) {
const v = readU32(buf, offset);
offset += 4;
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(` - ${v} (${prop})`);
}
console.log(` ${name}: RefArray: ${v}, (${kindName}, ${prop})`);
} else if (kind === PropFlags.Bool) {
const v = buf[offset];
offset += 1;
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(` ${name}: ${v} (${kindName}, ${prop})`);
} else if (kind === PropFlags.String) {
const v = readU32(buf, offset);
offset += 4;
const raw = getString(ctx.strTable, v);
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(
` ${name}: ${getString(ctx.strTable, v)} (${kindName}, ${prop})`,
);
console.log(` ${name}: ${raw} (${kindName}, ${prop})`);
} else if (kind === PropFlags.Number) {
const v = readU32(buf, offset);
offset += 4;
const raw = getString(ctx.strTable, v);
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(
` ${name}: ${getString(ctx.strTable, v)} (${kindName}, ${prop})`,
);
console.log(` ${name}: ${raw} (${kindName}, ${prop})`);
} else if (kind === PropFlags.Regex) {
const v = readU32(buf, offset);
offset += 4;
const raw = getString(ctx.strTable, v);
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(
` ${name}: ${getString(ctx.strTable, v)} (${kindName}, ${prop})`,
);
console.log(` ${name}: ${raw} (${kindName}, ${prop})`);
} else if (kind === PropFlags.Null) {
// @ts-ignore dump fn
// deno-lint-ignore no-console
@ -1250,8 +1279,21 @@ function _dump(ctx) {
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(` ${name}: undefined (${kindName}, ${prop})`);
} else if (kind === PropFlags.BigInt) {
const raw = getString(ctx.strTable, v);
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(` ${name}: ${raw} (${kindName}, ${prop})`);
} else if (kind === PropFlags.Obj) {
// @ts-ignore dump fn
// deno-lint-ignore no-console
console.log(` ${name}: Object (${v}) (${kindName}, ${prop})`);
// FIXME: Materialize object
}
}
idx++;
}
}

View file

@ -12,6 +12,7 @@ export interface AstContext {
strTableOffset: number;
rootOffset: number;
nodes: Map<number, NodeFacade>;
spansOffset: number;
strByType: number[];
strByProp: number[];
typeByStr: Map<string, number>;

View file

@ -138,27 +138,6 @@ pub struct NodeRef(pub u32);
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct PendingRef(pub u32);
#[derive(Debug)]
pub struct KindPropCount(pub u8, u8);
impl KindPropCount {
fn set_kind(&mut self, kind: u8) {
self.0 = kind;
}
fn set_prop_count(&mut self, count: u8) {
self.1 = count;
}
}
#[derive(Debug)]
struct Node {
kind: KindPropCount,
child: NodeRef,
next: NodeRef,
parent: NodeRef,
}
pub trait AstBufSerializer {
fn serialize(&mut self) -> Vec<u8>;
}
@ -169,13 +148,12 @@ pub struct SerializeCtx {
start_buf: NodeRef,
nodes: Vec<Node>,
/// Node buffer for traversal
buf: Vec<u8>,
field_buf: Vec<u8>,
/// Vec of spans
spans: Vec<u8>,
spans: Vec<u32>,
/// Maps string id to the actual string
str_table: StringTable,
@ -191,10 +169,11 @@ pub struct SerializeCtx {
}
/// <type u8>
/// <prop offset u32>
/// <child idx u32>
/// <next idx u32>
/// <parent idx u32>
const NODE_SIZE: u32 = 1 + 4 + 4 + 4;
const NODE_SIZE: u32 = 1 + 4 + 4 + 4 + 4;
/// This is the internal context used to allocate and fill the buffer. The point
/// is to be able to write absolute offsets directly in place.
@ -219,8 +198,6 @@ impl SerializeCtx {
field_count: 0,
field_offset: 0,
prev_sibling_node: None,
nodes: vec![],
};
let empty_str = ctx.str_table.insert("");
@ -229,7 +206,7 @@ impl SerializeCtx {
ctx.append_node(0, &DUMMY_SP);
ctx.kind_name_map[0] = empty_str;
ctx.kind_name_map[1] = empty_str;
ctx.start_buf = NodeRef(ctx.buf.len());
ctx.start_buf = NodeRef(ctx.buf.len() as u32);
// Insert default props that are always present
let type_str = ctx.str_table.insert("type");
@ -301,7 +278,13 @@ impl SerializeCtx {
self.prev_sibling_node = Some(ref_id)
}
fn append_inner(&mut self, kind: u8, span_lo: u32, span_hi: u32) {
fn append_inner(
&mut self,
kind: u8,
field_offset: usize,
span_lo: u32,
span_hi: u32,
) {
// type
self.buf.push(kind);
@ -312,14 +295,15 @@ impl SerializeCtx {
}
}
// child idx + next idx + parent idx
// field offset + child idx + next idx + parent idx
append_usize(&mut self.buf, field_offset);
append_usize(&mut self.buf, 0);
append_usize(&mut self.buf, 0);
append_usize(&mut self.buf, 0);
// write spans
append_u32(&mut self.spans, span_lo);
append_u32(&mut self.spans, span_hi);
self.spans.push(span_lo);
self.spans.push(span_hi);
}
/// The node buffer contains enough information for traversal
@ -329,13 +313,13 @@ impl SerializeCtx {
{
let id = self.get_id();
// type
let kind_u8 = kind.clone().into();
self.append_inner(kind_u8, span.lo.0, span.hi.0);
self.field_offset = self.field_buf.len();
self.field_buf.push(0);
// type
let kind_u8 = kind.clone().into();
self.append_inner(kind_u8, self.field_offset, span.lo.0, span.hi.0);
PendingRef(id)
}
@ -356,7 +340,7 @@ impl SerializeCtx {
append_usize(&mut self.field_buf, len);
}
/// Allocate an undefined field
/// Allocate an null field
pub fn write_null<P>(&mut self, prop: P)
where
P: Into<u8> + Display + Clone,
@ -376,6 +360,28 @@ impl SerializeCtx {
append_usize(&mut self.field_buf, id);
}
/// Allocate a bigint field
pub fn write_bigint<P>(&mut self, prop: P, value: &str)
where
P: Into<u8> + Display + Clone,
{
self.field_header(prop, PropFlags::BigInt);
let id = self.str_table.insert(value);
append_usize(&mut self.field_buf, id);
}
/// Allocate a RegExp field
pub fn write_regex<P>(&mut self, prop: P, value: &str)
where
P: Into<u8> + Display + Clone,
{
self.field_header(prop, PropFlags::Regex);
let id = self.str_table.insert(value);
append_usize(&mut self.field_buf, id);
}
/// Store the string in our string table and save the id of the string
/// in the current field.
pub fn write_str<P>(&mut self, prop: P, value: &str)
@ -444,7 +450,8 @@ impl SerializeCtx {
append_u32(&mut self.field_buf, group_id);
self.append_inner(GROUP_KIND, 0, 0);
// TODO(@marvinhagemeister) This is wrong
self.append_inner(GROUP_KIND, 0, 0, 0);
self.update_parent_link(parent.0, group_id);
for item in value {
@ -500,14 +507,23 @@ impl SerializeCtx {
append_usize(&mut buf, *v);
}
// Spans are rarely needed, so they're stored in a separate array.
// They're indexed by the node id.
let offset_spans = buf.len();
append_usize(&mut buf, self.spans.len());
for v in &self.spans {
append_u32(&mut buf, *v);
}
// Putting offsets of relevant parts of the buffer at the end. This
// allows us to hop to the relevant part by merely looking at the last
// for values in the message. Each value represents an offset into the
// buffer.
append_usize(&mut buf, offset_spans);
append_usize(&mut buf, offset_kind_map);
append_usize(&mut buf, offset_prop_map);
append_usize(&mut buf, offset_str_table);
append_usize(&mut buf, self.start_buf.0);
append_u32(&mut buf, self.start_buf.0);
buf
}

View file

@ -1286,8 +1286,8 @@ fn serialize_decl(ctx: &mut TsEsTreeBuilder, decl: &Decl) -> NodeRef {
}
fn serialize_ts_index_sig(
ctx: &mut TsEsTreeBuilder,
node: &TsIndexSignature,
_ctx: &mut TsEsTreeBuilder,
_node: &TsIndexSignature,
) -> NodeRef {
todo!()
// let raw = ctx.header(AstNode::TSMethodSignature, parent, &node.span);

View file

@ -1570,7 +1570,7 @@ impl TsEsTreeBuilder {
self.ctx.commit_node(id)
}
pub fn write_ts_class_implements(
pub fn _write_ts_class_implements(
&mut self,
span: &Span,
expr: NodeRef,