-
Notifications
You must be signed in to change notification settings - Fork 326
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Syntactic synchronization, automatic parentheses, metadata in Ast (#8893
) - Synchronize Y.Js clients by AST (implements #8237). - Before committing an edit, insert any parentheses-nodes needed for the concrete syntax to reflect tree structure (fixes #8884). - Move `externalId` and all node metadata into a Y.Map owned by each `Ast`. This allows including metadata changes in an edit, enables Y.Js merging of changes to different metadata fields, and will enable the use of Y.Js objects in metadata. (Implements #8804.) ### Important Notes - Metadata is now set and retrieved through accessors on the `Ast` objects. - Since some metadata edits need to take effect in real time (e.g. node dragging), new lower-overhead APIs (`commitDirect`, `skipTreeRepair`) are provided for careful use in certain cases. - The client is now bundled as ESM. - The build script cleans up git-untracked generated files in an outdated location, which fixes lint errors related to `src/generated` that may occur when switching branches.
- Loading branch information
Showing
59 changed files
with
4,475 additions
and
3,550 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import init, { | ||
is_ident_or_operator, | ||
parse_doc_to_json, | ||
parse as parse_tree, | ||
} from '../../rust-ffi/pkg/rust_ffi' | ||
import { isNode } from '../util/detect' | ||
|
||
export async function initializeFFI(path?: string | undefined) { | ||
if (isNode) { | ||
const fs = await import('node:fs/promises') | ||
const buffer = fs.readFile(path ?? './rust-ffi/pkg/rust_ffi_bg.wasm') | ||
await init(buffer) | ||
} else { | ||
await init() | ||
} | ||
} | ||
|
||
// TODO[ao]: We cannot to that, because the ffi is used by cjs modules. | ||
// await initializeFFI() | ||
|
||
// eslint-disable-next-line camelcase | ||
export { is_ident_or_operator, parse_doc_to_json, parse_tree } |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import * as random from 'lib0/random' | ||
import type { ExternalId } from '../yjsModel' | ||
import type { Module } from './mutableModule' | ||
import type { SyncTokenId } from './token' | ||
import type { AstId } from './tree' | ||
import { Ast, MutableAst } from './tree' | ||
|
||
export * from './mutableModule' | ||
export * from './parse' | ||
export * from './token' | ||
export * from './tree' | ||
|
||
declare const brandOwned: unique symbol | ||
/** Used to mark references required to be unique. | ||
* | ||
* Note that the typesystem cannot stop you from copying an `Owned`, | ||
* but that is an easy mistake to see (because it occurs locally). | ||
* | ||
* We can at least require *obtaining* an `Owned`, | ||
* which statically prevents the otherwise most likely usage errors when rearranging ASTs. | ||
*/ | ||
export type Owned<T = MutableAst> = T & { [brandOwned]: never } | ||
/** @internal */ | ||
export function asOwned<T>(t: T): Owned<T> { | ||
return t as Owned<T> | ||
} | ||
|
||
export type NodeChild<T = AstId | SyncTokenId> = { whitespace?: string | undefined; node: T } | ||
|
||
export function newExternalId(): ExternalId { | ||
return random.uuidv4() as ExternalId | ||
} | ||
|
||
/** @internal */ | ||
export function parentId(ast: Ast): AstId | undefined { | ||
return ast.fields.get('parent') | ||
} | ||
|
||
/** Returns the given IDs, and the IDs of all their ancestors. */ | ||
export function subtrees(module: Module, ids: Iterable<AstId>) { | ||
const subtrees = new Set<AstId>() | ||
for (const id of ids) { | ||
let ast = module.get(id) | ||
while (ast != null && !subtrees.has(ast.id)) { | ||
subtrees.add(ast.id) | ||
ast = ast.parent() | ||
} | ||
} | ||
return subtrees | ||
} | ||
|
||
/** Returns the IDs of the ASTs that are not descendants of any others in the given set. */ | ||
export function subtreeRoots(module: Module, ids: Set<AstId>) { | ||
const roots = new Array<AstId>() | ||
for (const id of ids) { | ||
const astInModule = module.get(id) | ||
if (!astInModule) continue | ||
let ast = astInModule.parent() | ||
let hasParentInSet | ||
while (ast != null) { | ||
if (ids.has(ast.id)) { | ||
hasParentInSet = true | ||
break | ||
} | ||
ast = ast.parent() | ||
} | ||
if (!hasParentInSet) roots.push(id) | ||
} | ||
return roots | ||
} |
Oops, something went wrong.