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

View file

@ -138,27 +138,6 @@ pub struct NodeRef(pub u32);
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct PendingRef(pub u32); 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 { pub trait AstBufSerializer {
fn serialize(&mut self) -> Vec<u8>; fn serialize(&mut self) -> Vec<u8>;
} }
@ -169,13 +148,12 @@ pub struct SerializeCtx {
start_buf: NodeRef, start_buf: NodeRef,
nodes: Vec<Node>,
/// Node buffer for traversal /// Node buffer for traversal
buf: Vec<u8>, buf: Vec<u8>,
field_buf: Vec<u8>, field_buf: Vec<u8>,
/// Vec of spans /// Vec of spans
spans: Vec<u8>, spans: Vec<u32>,
/// Maps string id to the actual string /// Maps string id to the actual string
str_table: StringTable, str_table: StringTable,
@ -191,10 +169,11 @@ pub struct SerializeCtx {
} }
/// <type u8> /// <type u8>
/// <prop offset u32>
/// <child idx u32> /// <child idx u32>
/// <next idx u32> /// <next idx u32>
/// <parent 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 /// 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. /// is to be able to write absolute offsets directly in place.
@ -219,8 +198,6 @@ impl SerializeCtx {
field_count: 0, field_count: 0,
field_offset: 0, field_offset: 0,
prev_sibling_node: None, prev_sibling_node: None,
nodes: vec![],
}; };
let empty_str = ctx.str_table.insert(""); let empty_str = ctx.str_table.insert("");
@ -229,7 +206,7 @@ impl SerializeCtx {
ctx.append_node(0, &DUMMY_SP); ctx.append_node(0, &DUMMY_SP);
ctx.kind_name_map[0] = empty_str; ctx.kind_name_map[0] = empty_str;
ctx.kind_name_map[1] = 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 // Insert default props that are always present
let type_str = ctx.str_table.insert("type"); let type_str = ctx.str_table.insert("type");
@ -301,7 +278,13 @@ impl SerializeCtx {
self.prev_sibling_node = Some(ref_id) 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 // type
self.buf.push(kind); 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); append_usize(&mut self.buf, 0);
append_usize(&mut self.buf, 0); append_usize(&mut self.buf, 0);
// write spans // write spans
append_u32(&mut self.spans, span_lo); self.spans.push(span_lo);
append_u32(&mut self.spans, span_hi); self.spans.push(span_hi);
} }
/// The node buffer contains enough information for traversal /// The node buffer contains enough information for traversal
@ -329,13 +313,13 @@ impl SerializeCtx {
{ {
let id = self.get_id(); 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_offset = self.field_buf.len();
self.field_buf.push(0); 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) PendingRef(id)
} }
@ -356,7 +340,7 @@ impl SerializeCtx {
append_usize(&mut self.field_buf, len); append_usize(&mut self.field_buf, len);
} }
/// Allocate an undefined field /// Allocate an null field
pub fn write_null<P>(&mut self, prop: P) pub fn write_null<P>(&mut self, prop: P)
where where
P: Into<u8> + Display + Clone, P: Into<u8> + Display + Clone,
@ -376,6 +360,28 @@ impl SerializeCtx {
append_usize(&mut self.field_buf, id); 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 /// Store the string in our string table and save the id of the string
/// in the current field. /// in the current field.
pub fn write_str<P>(&mut self, prop: P, value: &str) 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); 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); self.update_parent_link(parent.0, group_id);
for item in value { for item in value {
@ -500,14 +507,23 @@ impl SerializeCtx {
append_usize(&mut buf, *v); 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 // 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 // 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 // for values in the message. Each value represents an offset into the
// buffer. // buffer.
append_usize(&mut buf, offset_spans);
append_usize(&mut buf, offset_kind_map); append_usize(&mut buf, offset_kind_map);
append_usize(&mut buf, offset_prop_map); append_usize(&mut buf, offset_prop_map);
append_usize(&mut buf, offset_str_table); append_usize(&mut buf, offset_str_table);
append_usize(&mut buf, self.start_buf.0); append_u32(&mut buf, self.start_buf.0);
buf buf
} }

View file

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

View file

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