mirror of
https://github.com/hexedtech/codemp.git
synced 2024-11-22 07:14:50 +01:00
feat: bindings for changes and callback
This commit is contained in:
parent
06523b2325
commit
4563cfdd09
1 changed files with 72 additions and 18 deletions
|
@ -2,7 +2,11 @@ use std::sync::Arc;
|
|||
|
||||
use neon::prelude::*;
|
||||
use once_cell::sync::OnceCell;
|
||||
use codemp::{cursor::Cursor, client::CodempClient, tokio::{runtime::Runtime, sync::{Mutex, broadcast}}, proto::buffer_client::BufferClient, operation::{OperationController, OperationFactory}};
|
||||
use codemp::{
|
||||
cursor::Cursor, client::CodempClient, operation::{OperationController, OperationFactory, OperationProcessor},
|
||||
proto::buffer_client::BufferClient,
|
||||
};
|
||||
use codemp::tokio::{runtime::Runtime, sync::{Mutex, broadcast}};
|
||||
|
||||
fn runtime<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'static Runtime> {
|
||||
static RUNTIME: OnceCell<Runtime> = OnceCell::new();
|
||||
|
@ -52,8 +56,8 @@ fn create(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
|||
let content = cx.argument::<JsString>(1).ok().map(|x| x.value(&mut cx));
|
||||
let this = cx.this();
|
||||
let boxed : Handle<JsBox<ClientHandle>> = this.get(&mut cx, "boxed")?;
|
||||
let rc = boxed.0.clone();
|
||||
|
||||
let rc = boxed.0.clone();
|
||||
let (deferred, promise) = cx.promise();
|
||||
let channel = cx.channel();
|
||||
|
||||
|
@ -70,8 +74,8 @@ fn create(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
|||
fn listen(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
||||
let this = cx.this();
|
||||
let boxed : Handle<JsBox<ClientHandle>> = this.get(&mut cx, "boxed")?;
|
||||
let rc = boxed.0.clone();
|
||||
|
||||
let rc = boxed.0.clone();
|
||||
let (deferred, promise) = cx.promise();
|
||||
let channel = cx.channel();
|
||||
|
||||
|
@ -98,9 +102,9 @@ fn listen(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
|||
fn attach(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
||||
let this = cx.this();
|
||||
let boxed : Handle<JsBox<ClientHandle>> = this.get(&mut cx, "boxed")?;
|
||||
let rc = boxed.0.clone();
|
||||
let path = cx.argument::<JsString>(0)?.value(&mut cx);
|
||||
|
||||
let rc = boxed.0.clone();
|
||||
let (deferred, promise) = cx.promise();
|
||||
let channel = cx.channel();
|
||||
|
||||
|
@ -111,10 +115,14 @@ fn attach(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
|||
let obj = cx.empty_object();
|
||||
let boxed_value = cx.boxed(OperationControllerHandle(controller));
|
||||
obj.set(&mut cx, "boxed", boxed_value)?;
|
||||
let apply_method = JsFunction::new(&mut cx, apply_operation)?;
|
||||
obj.set(&mut cx, "apply", apply_method)?;
|
||||
let poll_method = JsFunction::new(&mut cx, poll_operation)?;
|
||||
obj.set(&mut cx, "poll", poll_method)?;
|
||||
let content_method = JsFunction::new(&mut cx, content_operation)?;
|
||||
obj.set(&mut cx, "content", content_method)?;
|
||||
let callback_method = JsFunction::new(&mut cx, callback_operation)?;
|
||||
obj.set(&mut cx, "set_callback", callback_method)?;
|
||||
Ok(obj)
|
||||
})
|
||||
},
|
||||
|
@ -128,18 +136,19 @@ fn attach(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
|||
fn cursor(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
||||
let this = cx.this();
|
||||
let boxed : Handle<JsBox<ClientHandle>> = this.get(&mut cx, "boxed")?;
|
||||
let rc = boxed.0.clone();
|
||||
let path = cx.argument::<JsString>(0)?.value(&mut cx);
|
||||
let row = cx.argument::<JsNumber>(0)?.value(&mut cx) as i64;
|
||||
let col = cx.argument::<JsNumber>(0)?.value(&mut cx) as i64;
|
||||
|
||||
let path = cx.argument::<JsString>(0)?.value(&mut cx);
|
||||
let row = cx.argument::<JsNumber>(1)?.value(&mut cx) as i64;
|
||||
let col = cx.argument::<JsNumber>(2)?.value(&mut cx) as i64;
|
||||
|
||||
let rc = boxed.0.clone();
|
||||
let (deferred, promise) = cx.promise();
|
||||
let channel = cx.channel();
|
||||
|
||||
runtime(&mut cx)?.spawn(async move {
|
||||
match rc.lock().await.cursor(path, row, col).await {
|
||||
Ok(accepted) => deferred.settle_with(&channel, move |mut cx| Ok(cx.boolean(accepted))),
|
||||
Err(e) => deferred.settle_with(&channel, move |mut cx| cx.throw_error::<String, neon::handle::Handle<JsString>>(e.to_string())),
|
||||
Err(e) => deferred.settle_with(&channel, move |mut cx| cx.throw_error::<_, Handle<JsString>>(e.to_string())),
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -150,11 +159,40 @@ fn cursor(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
|||
struct OperationControllerHandle(Arc<OperationController>);
|
||||
impl Finalize for OperationControllerHandle {}
|
||||
|
||||
fn apply_operation(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
||||
let this = cx.this();
|
||||
let boxed : Handle<JsBox<OperationControllerHandle>> = this.get(&mut cx, "boxed")?;
|
||||
let skip = cx.argument::<JsNumber>(0)?.value(&mut cx).round() as usize;
|
||||
let text = cx.argument::<JsString>(1)?.value(&mut cx);
|
||||
let tail = cx.argument::<JsNumber>(2)?.value(&mut cx).round() as usize;
|
||||
|
||||
let rc = boxed.0.clone();
|
||||
let (deferred, promise) = cx.promise();
|
||||
let channel = cx.channel();
|
||||
|
||||
runtime(&mut cx)?.spawn(async move {
|
||||
let op = rc.delta(skip, text.as_str(), tail);
|
||||
match rc.apply(op) {
|
||||
Err(e) => deferred.settle_with(&channel, move |mut cx| cx.throw_error::<_, Handle<JsString>>(format!("could not apply operation: {}", e))),
|
||||
Ok(span) => deferred.settle_with(&channel, move |mut cx| {
|
||||
let obj = cx.empty_array();
|
||||
let start_value = cx.number(span.start as u32);
|
||||
obj.set(&mut cx, 0, start_value)?;
|
||||
let end_value = cx.number(span.end as u32);
|
||||
obj.set(&mut cx, 1, end_value)?;
|
||||
Ok(obj)
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
Ok(promise)
|
||||
}
|
||||
|
||||
fn poll_operation(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
||||
let this = cx.this();
|
||||
let boxed : Handle<JsBox<OperationControllerHandle>> = this.get(&mut cx, "boxed")?;
|
||||
let rc = boxed.0.clone();
|
||||
|
||||
let rc = boxed.0.clone();
|
||||
let (deferred, promise) = cx.promise();
|
||||
let channel = cx.channel();
|
||||
|
||||
|
@ -173,22 +211,38 @@ fn poll_operation(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
|||
Ok(promise)
|
||||
}
|
||||
|
||||
fn content_operation(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
||||
fn content_operation(mut cx: FunctionContext) -> JsResult<JsString> {
|
||||
let this = cx.this();
|
||||
let boxed : Handle<JsBox<OperationControllerHandle>> = this.get(&mut cx, "boxed")?;
|
||||
let rc = boxed.0.clone();
|
||||
Ok(cx.string(boxed.0.content()))
|
||||
}
|
||||
|
||||
let (deferred, promise) = cx.promise();
|
||||
fn callback_operation(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
let this = cx.this();
|
||||
let boxed : Handle<JsBox<OperationControllerHandle>> = this.get(&mut cx, "boxed")?;
|
||||
let callback = Arc::new(cx.argument::<JsFunction>(0)?.root(&mut cx));
|
||||
|
||||
let rc = boxed.0.clone();
|
||||
let channel = cx.channel();
|
||||
|
||||
// TODO when garbage collecting OperationController stop this worker
|
||||
runtime(&mut cx)?.spawn(async move {
|
||||
let content = rc.content();
|
||||
deferred.settle_with(&channel, move |mut cx| {
|
||||
Ok(cx.string(content))
|
||||
loop{
|
||||
let span = rc.wait().await;
|
||||
let cb = callback.clone();
|
||||
channel.send(move |mut cx| {
|
||||
cb.to_inner(&mut cx)
|
||||
.call_with(&cx)
|
||||
.arg(cx.number(span.start as i32))
|
||||
.arg(cx.number(span.end as i32))
|
||||
.apply::<JsUndefined, _>(&mut cx)?;
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Ok(promise)
|
||||
Ok(cx.undefined())
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue