Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/docs/binding-cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ The private `unique symbol` is a phantom marker: it keeps an ordinary bigint fro
The bigint logically contains a tree identity, a binding-issued serial for that node creation, and the raw Taffy NodeId. The exact field widths and encoding are not public. Each public tree wrapper keeps a private registry such as:

```ts
#inner: NativeTaffyTree;
#inner: BindingTaffyTree;
#nodes: PrivateNodeRegistry;
```

Expand Down
4 changes: 2 additions & 2 deletions crates/taffyjs_binding/src/available_space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use napi::bindgen_prelude::Unknown;
use napi_derive::napi;
use taffy::style::AvailableSpace;

use crate::error::NativeResult;
use crate::error::BindingResult;
use crate::number::to_f32;
use crate::numeric::AvailableSpaceKindCode;
use crate::tagged_values::{AvailableSpaceInputValue, parse_available_space};
Expand All @@ -13,7 +13,7 @@ pub struct AvailableSpaceOutput {
pub value: Option<f64>,
}

pub(crate) fn available_space(value: Unknown<'_>) -> NativeResult<AvailableSpace> {
pub(crate) fn available_space(value: Unknown<'_>) -> BindingResult<AvailableSpace> {
Ok(match parse_available_space(value)? {
AvailableSpaceInputValue::Definite(value) => AvailableSpace::Definite(to_f32(value)),
AvailableSpaceInputValue::MinContent => AvailableSpace::MinContent,
Expand Down
60 changes: 30 additions & 30 deletions crates/taffyjs_binding/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,81 +1,81 @@
use napi::{Env, Error, Result, Status};

#[derive(Clone, Copy, Debug)]
enum NativeErrorKind {
enum BindingErrorKind {
Error,
RangeError,
TypeError,
}

#[derive(Debug)]
pub(crate) struct NativeError {
kind: NativeErrorKind,
pub(crate) struct BindingError {
kind: BindingErrorKind,
pub(crate) code: Option<&'static str>,
message: String,
}

pub(crate) type NativeResult<T> = std::result::Result<T, NativeError>;
pub(crate) type BindingResult<T> = std::result::Result<T, BindingError>;

fn native_error(
kind: NativeErrorKind,
fn binding_error(
kind: BindingErrorKind,
code: Option<&'static str>,
message: impl Into<String>,
) -> NativeError {
NativeError {
) -> BindingError {
BindingError {
kind,
code,
message: message.into(),
}
}

fn coded_error(code: &'static str, message: impl Into<String>) -> NativeError {
native_error(NativeErrorKind::Error, Some(code), message)
fn coded_error(code: &'static str, message: impl Into<String>) -> BindingError {
binding_error(BindingErrorKind::Error, Some(code), message)
}

#[allow(dead_code)]
fn coded_range_error(code: &'static str, message: impl Into<String>) -> NativeError {
native_error(NativeErrorKind::RangeError, Some(code), message)
fn coded_range_error(code: &'static str, message: impl Into<String>) -> BindingError {
binding_error(BindingErrorKind::RangeError, Some(code), message)
}

#[allow(dead_code)]
pub(crate) fn plain_error(message: impl Into<String>) -> NativeError {
native_error(NativeErrorKind::Error, None, message)
pub(crate) fn plain_error(message: impl Into<String>) -> BindingError {
binding_error(BindingErrorKind::Error, None, message)
}

pub(crate) fn range_error(message: impl Into<String>) -> NativeError {
native_error(NativeErrorKind::RangeError, None, message)
pub(crate) fn range_error(message: impl Into<String>) -> BindingError {
binding_error(BindingErrorKind::RangeError, None, message)
}

pub(crate) fn type_error(message: impl Into<String>) -> NativeError {
native_error(NativeErrorKind::TypeError, None, message)
pub(crate) fn type_error(message: impl Into<String>) -> BindingError {
binding_error(BindingErrorKind::TypeError, None, message)
}

#[allow(dead_code)]
pub(crate) fn child_index_out_of_bounds_error(message: impl Into<String>) -> NativeError {
pub(crate) fn child_index_out_of_bounds_error(message: impl Into<String>) -> BindingError {
coded_range_error("ERR_TAFFY_CHILD_INDEX_OUT_OF_BOUNDS", message)
}

#[allow(dead_code)]
pub(crate) fn invalid_node_id_error(message: impl Into<String>) -> NativeError {
pub(crate) fn invalid_node_id_error(message: impl Into<String>) -> BindingError {
coded_error("ERR_TAFFY_INVALID_NODE_ID", message)
}

#[allow(dead_code)]
pub(crate) fn foreign_node_id_error(message: impl Into<String>) -> NativeError {
pub(crate) fn foreign_node_id_error(message: impl Into<String>) -> BindingError {
coded_error("ERR_TAFFY_FOREIGN_NODE_ID", message)
}

#[allow(dead_code)]
pub(crate) fn stale_node_id_error(message: impl Into<String>) -> NativeError {
pub(crate) fn stale_node_id_error(message: impl Into<String>) -> BindingError {
coded_error("ERR_TAFFY_STALE_NODE_ID", message)
}

#[allow(dead_code)]
pub(crate) fn invalid_topology_error(message: impl Into<String>) -> NativeError {
pub(crate) fn invalid_topology_error(message: impl Into<String>) -> BindingError {
coded_error("ERR_TAFFY_INVALID_TOPOLOGY", message)
}

pub(crate) fn busy_error(public_method: &str) -> NativeError {
pub(crate) fn busy_error(public_method: &str) -> BindingError {
coded_error(
"ERR_TAFFY_TREE_BUSY",
format!(
Expand All @@ -84,28 +84,28 @@ pub(crate) fn busy_error(public_method: &str) -> NativeError {
)
}

pub(crate) fn internal_error() -> NativeError {
pub(crate) fn internal_error() -> BindingError {
coded_error(
"ERR_TAFFY_INTERNAL",
"An unexpected internal Taffy error occurred",
)
}

pub(crate) fn poisoned_error() -> NativeError {
pub(crate) fn poisoned_error() -> BindingError {
coded_error(
"ERR_TAFFY_TREE_POISONED",
"This TaffyTree cannot be used after an unexpected internal failure",
)
}

pub(crate) fn into_napi<T>(env: Env, result: NativeResult<T>) -> Result<T> {
pub(crate) fn into_napi<T>(env: Env, result: BindingResult<T>) -> Result<T> {
match result {
Ok(value) => Ok(value),
Err(error) => {
match error.kind {
NativeErrorKind::Error => env.throw_error(&error.message, error.code),
NativeErrorKind::RangeError => env.throw_range_error(&error.message, error.code),
NativeErrorKind::TypeError => env.throw_type_error(&error.message, error.code),
BindingErrorKind::Error => env.throw_error(&error.message, error.code),
BindingErrorKind::RangeError => env.throw_range_error(&error.message, error.code),
BindingErrorKind::TypeError => env.throw_type_error(&error.message, error.code),
}?;
Err(Error::new(Status::PendingException, error.message))
}
Expand Down
22 changes: 11 additions & 11 deletions crates/taffyjs_binding/src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use napi::bindgen_prelude::Unknown;
use napi_derive::napi;
use taffy::geometry::{Line, Point, Rect, Size};

use crate::error::NativeResult;
use crate::error::BindingResult;
use crate::js_object;

const POINT_FIELDS: &[&str] = &["x", "y"];
Expand Down Expand Up @@ -45,8 +45,8 @@ pub struct PartialLineInput<'env> {
pub(crate) fn partial_point<T>(
value: Unknown<'_>,
default: Point<T>,
mut convert: impl FnMut(f64) -> NativeResult<T>,
) -> NativeResult<Point<T>> {
mut convert: impl FnMut(f64) -> BindingResult<T>,
) -> BindingResult<Point<T>> {
let input: PartialPointInput = js_object::input(value, "a Point object", Some(POINT_FIELDS))?;
Ok(Point {
x: input.x.map(&mut convert).transpose()?.unwrap_or(default.x),
Expand All @@ -56,8 +56,8 @@ pub(crate) fn partial_point<T>(

pub(crate) fn size<'env, T>(
value: Unknown<'env>,
mut convert: impl FnMut(Unknown<'env>) -> NativeResult<T>,
) -> NativeResult<Size<T>> {
mut convert: impl FnMut(Unknown<'env>) -> BindingResult<T>,
) -> BindingResult<Size<T>> {
let input: CompleteSizeInput<'env> =
js_object::input(value, "a Size object", Some(SIZE_FIELDS))?;
Ok(Size {
Expand All @@ -69,8 +69,8 @@ pub(crate) fn size<'env, T>(
pub(crate) fn partial_size<'env, T>(
value: Unknown<'env>,
default: Size<T>,
mut convert: impl FnMut(Unknown<'env>) -> NativeResult<T>,
) -> NativeResult<Size<T>> {
mut convert: impl FnMut(Unknown<'env>) -> BindingResult<T>,
) -> BindingResult<Size<T>> {
let input: PartialSizeInput<'env> =
js_object::input(value, "a Size object", Some(SIZE_FIELDS))?;
Ok(Size {
Expand All @@ -90,8 +90,8 @@ pub(crate) fn partial_size<'env, T>(
pub(crate) fn partial_rect<'env, T>(
value: Unknown<'env>,
default: Rect<T>,
mut convert: impl FnMut(Unknown<'env>) -> NativeResult<T>,
) -> NativeResult<Rect<T>> {
mut convert: impl FnMut(Unknown<'env>) -> BindingResult<T>,
) -> BindingResult<Rect<T>> {
let input: PartialRectInput<'env> =
js_object::input(value, "a Rect object", Some(RECT_FIELDS))?;
Ok(Rect {
Expand Down Expand Up @@ -121,8 +121,8 @@ pub(crate) fn partial_rect<'env, T>(
pub(crate) fn partial_line<'env, T>(
value: Unknown<'env>,
default: Line<T>,
mut convert: impl FnMut(Unknown<'env>) -> NativeResult<T>,
) -> NativeResult<Line<T>> {
mut convert: impl FnMut(Unknown<'env>) -> BindingResult<T>,
) -> BindingResult<Line<T>> {
let input: PartialLineInput<'env> =
js_object::input(value, "a Line object", Some(LINE_FIELDS))?;
Ok(Line {
Expand Down
36 changes: 18 additions & 18 deletions crates/taffyjs_binding/src/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use taffy::style::{
TrackSizingFunction,
};

use crate::error::{NativeResult, range_error, type_error};
use crate::error::{BindingResult, range_error, type_error};
use crate::js_object;
use crate::length::{self, LengthOutput};
use crate::number::{from_unknown, to_f32, to_integer};
Expand Down Expand Up @@ -113,22 +113,22 @@ pub struct GridTemplateAreasOutput {
pub column_count: u16,
}

fn tagged_input<'env>(value: Unknown<'env>, name: &str) -> NativeResult<TaggedGridInput<'env>> {
fn tagged_input<'env>(value: Unknown<'env>, name: &str) -> BindingResult<TaggedGridInput<'env>> {
js_object::input(value, name, None)
}

fn tagged_kind<T>(input: &TaggedGridInput<'_>) -> NativeResult<T>
fn tagged_kind<T>(input: &TaggedGridInput<'_>) -> BindingResult<T>
where
T: TryFrom<i64>,
{
to_integer(input.kind)
}

fn tagged_value<'env>(input: &TaggedGridInput<'env>, name: &str) -> NativeResult<Unknown<'env>> {
fn tagged_value<'env>(input: &TaggedGridInput<'env>, name: &str) -> BindingResult<Unknown<'env>> {
js_object::required(input.value, name)
}

pub(crate) fn grid_placement(value: Unknown<'_>) -> NativeResult<GridPlacement<String>> {
pub(crate) fn grid_placement(value: Unknown<'_>) -> BindingResult<GridPlacement<String>> {
let input: GridPlacementInput = js_object::input(value, "a GridPlacement object", None)?;
Ok(match to_integer::<GridPlacementKindCode>(input.kind)? {
GridPlacementKindCode::Auto => GridPlacement::Auto,
Expand All @@ -149,7 +149,7 @@ pub(crate) fn grid_placement(value: Unknown<'_>) -> NativeResult<GridPlacement<S
})
}

fn min_track(value: Unknown<'_>) -> NativeResult<MinTrackSizingFunction> {
fn min_track(value: Unknown<'_>) -> BindingResult<MinTrackSizingFunction> {
let input = tagged_input(value, "a minimum track object")?;
match tagged_kind::<TrackSizingKindCode>(&input)? {
TrackSizingKindCode::Length => Ok(MinTrackSizingFunction::length(to_f32(from_unknown(
Expand All @@ -168,7 +168,7 @@ fn min_track(value: Unknown<'_>) -> NativeResult<MinTrackSizingFunction> {
}
}

fn max_track(value: Unknown<'_>) -> NativeResult<MaxTrackSizingFunction> {
fn max_track(value: Unknown<'_>) -> BindingResult<MaxTrackSizingFunction> {
let input = tagged_input(value, "a maximum track object")?;
match tagged_kind::<TrackSizingKindCode>(&input)? {
TrackSizingKindCode::Length => Ok(MaxTrackSizingFunction::length(to_f32(from_unknown(
Expand Down Expand Up @@ -199,7 +199,7 @@ fn max_track(value: Unknown<'_>) -> NativeResult<MaxTrackSizingFunction> {
}
}

pub(crate) fn track_sizing(value: Unknown<'_>) -> NativeResult<TrackSizingFunction> {
pub(crate) fn track_sizing(value: Unknown<'_>) -> BindingResult<TrackSizingFunction> {
let input: TrackSizingInput<'_> =
js_object::input(value, "a TrackSizingFunction object", None)?;
Ok(TrackSizingFunction {
Expand All @@ -208,7 +208,7 @@ pub(crate) fn track_sizing(value: Unknown<'_>) -> NativeResult<TrackSizingFuncti
})
}

fn repetition_count(value: Unknown<'_>) -> NativeResult<RepetitionCount> {
fn repetition_count(value: Unknown<'_>) -> BindingResult<RepetitionCount> {
let input = tagged_input(value, "a RepetitionCount object")?;
Ok(match tagged_kind::<RepetitionCountKindCode>(&input)? {
RepetitionCountKindCode::Count => RepetitionCount::Count(to_integer::<u16>(from_unknown(
Expand All @@ -220,7 +220,7 @@ fn repetition_count(value: Unknown<'_>) -> NativeResult<RepetitionCount> {
})
}

fn template_repetition(value: Unknown<'_>) -> NativeResult<GridTemplateRepetition<String>> {
fn template_repetition(value: Unknown<'_>) -> BindingResult<GridTemplateRepetition<String>> {
let input: GridTemplateRepetitionInput<'_> =
js_object::input(value, "a GridTemplateRepetition object", None)?;
Ok(GridTemplateRepetition {
Expand All @@ -229,14 +229,14 @@ fn template_repetition(value: Unknown<'_>) -> NativeResult<GridTemplateRepetitio
.tracks
.into_iter()
.map(track_sizing)
.collect::<NativeResult<Vec<_>>>()?,
.collect::<BindingResult<Vec<_>>>()?,
line_names: input.line_names,
})
}

pub(crate) fn template_component(
value: Unknown<'_>,
) -> NativeResult<GridTemplateComponent<String>> {
) -> BindingResult<GridTemplateComponent<String>> {
let input = tagged_input(value, "a GridTemplateComponent object")?;
Ok(
match tagged_kind::<GridTemplateComponentKindCode>(&input)? {
Expand All @@ -252,17 +252,17 @@ pub(crate) fn template_component(

pub(crate) fn template_components(
values: Vec<Unknown<'_>>,
) -> NativeResult<Vec<GridTemplateComponent<String>>> {
) -> BindingResult<Vec<GridTemplateComponent<String>>> {
values
.into_iter()
.map(template_component)
.collect::<NativeResult<Vec<_>>>()
.collect::<BindingResult<Vec<_>>>()
}

pub(crate) fn validate_template_line_names(
values: &[GridTemplateComponent<String>],
top_level_line_names: &[Vec<String>],
) -> NativeResult<()> {
) -> BindingResult<()> {
for value in values.iter().take(top_level_line_names.len()) {
if let GridTemplateComponent::Repeat(repetition) = value
&& repetition.line_names.is_empty()
Expand All @@ -276,7 +276,7 @@ pub(crate) fn validate_template_line_names(
Ok(())
}

fn template_area(input: GridTemplateAreaInput) -> NativeResult<GridTemplateArea<String>> {
fn template_area(input: GridTemplateAreaInput) -> BindingResult<GridTemplateArea<String>> {
Ok(GridTemplateArea {
name: input.name,
row_start: to_integer::<u16>(input.row_start)?,
Expand All @@ -288,13 +288,13 @@ fn template_area(input: GridTemplateAreaInput) -> NativeResult<GridTemplateArea<

pub(crate) fn template_areas(
input: GridTemplateAreasInput,
) -> NativeResult<GridTemplateAreas<String>> {
) -> BindingResult<GridTemplateAreas<String>> {
Ok(GridTemplateAreas {
areas: input
.areas
.into_iter()
.map(template_area)
.collect::<NativeResult<Vec<_>>>()?,
.collect::<BindingResult<Vec<_>>>()?,
row_count: to_integer::<u16>(input.row_count)?,
column_count: to_integer::<u16>(input.column_count)?,
})
Expand Down
6 changes: 3 additions & 3 deletions crates/taffyjs_binding/src/js_object.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use napi::bindgen_prelude::{FromNapiValue, Object, Unknown};
use napi::{JsValue, ValueType};

use crate::error::{NativeResult, type_error};
use crate::error::{BindingResult, type_error};

pub(crate) fn input<'env, T>(
value: Unknown<'env>,
name: &str,
allowed_fields: Option<&[&str]>,
) -> NativeResult<T>
) -> BindingResult<T>
where
T: FromNapiValue,
{
Expand Down Expand Up @@ -49,6 +49,6 @@ where
}
}

pub(crate) fn required<T>(value: Option<T>, name: &str) -> NativeResult<T> {
pub(crate) fn required<T>(value: Option<T>, name: &str) -> BindingResult<T> {
value.ok_or_else(|| type_error(format!("{name} is required")))
}
Loading