0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-05 18:37:20 -05:00

add CancellationToken, but not wired up yet

This commit is contained in:
Bartek Iwańczuk 2024-12-26 11:18:49 +01:00
parent 05a89f5ffb
commit c1e3357d2c
No known key found for this signature in database
GPG key ID: 0C6BCDDC3B3AD750
3 changed files with 31 additions and 6 deletions

View file

@ -13,6 +13,7 @@ const {
op_lint_get_source,
op_lint_report,
op_lint_create_serialized_ast,
op_is_cancelled,
} = core.ops;
// Keep in sync with Rust
@ -61,6 +62,16 @@ const state = {
installedPlugins: new Set(),
};
/**
* This implementation calls into Rust to check if Tokio's cancellation token
* has already been canceled.
*/
class CancellationToken {
isCancellationRequested() {
return op_is_cancelled();
}
}
/**
* Every rule gets their own instance of this class. This is the main
* API lint rules interact with.
@ -893,10 +904,11 @@ export function runPluginsForFile(fileName, serializedAst) {
visitors.push({ info, matcher });
}
const token = new CancellationToken();
// Traverse ast with all visitors at the same time to avoid traversing
// multiple times.
try {
traverse(ctx, visitors, ctx.rootOffset);
traverse(ctx, visitors, ctx.rootOffset, token);
} finally {
ctx.nodes.clear();
@ -911,10 +923,12 @@ export function runPluginsForFile(fileName, serializedAst) {
* @param {AstContext} ctx
* @param {CompiledVisitor[]} visitors
* @param {number} offset
* @param {CancellationToken} cancellationToken
*/
function traverse(ctx, visitors, offset) {
function traverse(ctx, visitors, offset, cancellationToken) {
// The 0 offset is used to denote an empty/placeholder node
if (offset === 0) return;
if (cancellationToken.isCancellationRequested()) return;
const originalOffset = offset;
@ -925,8 +939,8 @@ function traverse(ctx, visitors, offset) {
for (let i = 0; i < visitors.length; i++) {
const v = visitors[i];
if (v.matcher(ctx.matcher, offset)) {
if (cancellationToken.isCancellationRequested()) return;
if (v.info.exit !== NOOP) {
if (exits === null) {
exits = [v.info.exit];
@ -952,13 +966,14 @@ function traverse(ctx, visitors, offset) {
offset += 1;
for (let i = 0; i < propCount; i++) {
if (cancellationToken.isCancellationRequested()) return;
const kind = buf[offset + 1];
offset += 2; // propId + propFlags
if (kind === PropFlags.Ref) {
const next = readU32(buf, offset);
offset += 4;
traverse(ctx, visitors, next);
traverse(ctx, visitors, next, cancellationToken);
} else if (kind === PropFlags.RefArr) {
const len = readU32(buf, offset);
offset += 4;
@ -966,7 +981,7 @@ function traverse(ctx, visitors, offset) {
for (let j = 0; j < len; j++) {
const child = readU32(buf, offset);
offset += 4;
traverse(ctx, visitors, child);
traverse(ctx, visitors, child, cancellationToken);
}
} else if (kind === PropFlags.String) {
offset += 4;

View file

@ -12,6 +12,7 @@ use deno_core::OpState;
use deno_lint::diagnostic::LintDiagnostic;
use deno_lint::diagnostic::LintDiagnosticDetails;
use deno_lint::diagnostic::LintDiagnosticRange;
use tokio_util::sync::CancellationToken;
use crate::tools::lint;
use crate::tools::lint::PluginLogger;
@ -21,7 +22,8 @@ deno_core::extension!(
ops = [
op_lint_create_serialized_ast,
op_lint_report,
op_lint_get_source
op_lint_get_source,
op_is_cancelled
],
options = {
logger: PluginLogger,
@ -40,6 +42,7 @@ deno_core::extension!(
pub struct LintPluginContainer {
pub diagnostics: Vec<LintDiagnostic>,
pub source_text_info: Option<SourceTextInfo>,
token: CancellationToken,
}
impl LintPluginContainer {
@ -88,6 +91,12 @@ pub fn op_print(state: &mut OpState, #[string] msg: &str, is_err: bool) {
}
}
#[op2(fast)]
fn op_is_cancelled(state: &mut OpState) -> bool {
let container = state.borrow_mut::<LintPluginContainer>();
container.token.is_cancelled()
}
#[op2]
#[buffer]
fn op_lint_create_serialized_ast(

View file

@ -533,6 +533,7 @@ const NOT_IMPORTED_OPS = [
"op_lint_report",
"op_lint_get_source",
"op_lint_create_serialized_ast",
"op_is_cancelled",
// Related to `Deno.test()` API
"op_test_event_step_result_failed",