const WRAPPER_RAISE_CONDITION_HELPER_FN: &str = "function(.val, .call_default) {\n # The condition object for one tagged value `.v`.\n .cond <- function(.v) {\n .msg <- .v$error\n # `.v$call` is the call the Rust side captured, NULL to use the wrapper\'s\n # call, or FALSE for a condition raised without one (`call = none`, R\'s\n # `call. = FALSE`), which is signalled with `call = NULL`.\n .call <- if (isFALSE(.v$call)) NULL else if (is.null(.v$call)) .call_default else .v$call\n # A generated S3 method passes its frame instead of a call, so that the\n # generic\'s call (`summary(x)` for `summary.cls(x)`, the assignment for a\n # replacement method) is built only now, when a condition is raised. The\n # resolver recovers the generic\'s call from that method frame.\n if (is.environment(.call)) .call <- .miniextendr_frame_call(.call)\n .class <- .v$class\n # `arg_error!` writes the class \".miniextendr_conversion_error_class\"\n # where the crate\'s `conversion_error_class` belongs: only the generated R\n # knows those classes, bound under that name at the end of the wrappers\n # preamble, so they replace it here. The copy of this helper that signals\n # deferred conditions lives in the base namespace, where the name is\n # unbound and the marker is dropped.\n .at <- match(\".miniextendr_conversion_error_class\", .class)\n if (!is.na(.at)) {\n .class <- append(.class[-.at], get0(\".miniextendr_conversion_error_class\", ifnotfound = NULL), after = .at - 1L)\n }\n # `.v$data` is an optional named list of structured fields (from the\n # macros\' `data = ...` form). When present, splice its named elements into\n # the condition object alongside message/call/kind so handlers can read\n # `e$<name>`. `utils::modifyList` keeps the base fields and appends the\n # data fields; a malformed (non-list / unnamed) payload is ignored.\n # `keep.null = TRUE`: a field the Rust side set to `RValue::Null` is a\n # present field whose value is NULL, and must stay in `names(e)`; the\n # default would silently drop it (found downstream via a\n # `RConditionData::data()` returning an explicit NULL entry).\n .data <- .v$data\n # A cause the Rust side attached (`RCondition::with_parent`) travels as\n # the tagged value `.mx_parent` and becomes the condition object\n # `e$parent`, as `rlang::abort(parent = )` chains conditions. It is not\n # signalled, and its classes stay out of this condition\'s.\n if (is.list(.data) && !is.null(.data[[\".mx_parent\", exact = TRUE]])) {\n .parent <- .cond(.data[[\".mx_parent\", exact = TRUE]])\n .data[[\".mx_parent\"]] <- NULL\n .data[[\"parent\"]] <- .parent\n }\n .cond_fields <- function(base) {\n if (is.null(.data) || !is.list(.data) || is.null(names(.data))) {\n base\n } else {\n utils::modifyList(base, .data, keep.null = TRUE)\n }\n }\n switch(.v$kind,\n warning = structure(.cond_fields(list(message = .msg, call = .call, kind = \"warning\")),\n class = c(.class, \"rust_warning\", \"simpleWarning\", \"warning\", \"condition\")),\n message = structure(.cond_fields(list(message = paste0(.msg, \"\\n\"), call = NULL, kind = \"message\")),\n class = c(.class, \"rust_message\", \"simpleMessage\", \"message\", \"condition\")),\n condition = structure(.cond_fields(list(message = .msg, call = .call, kind = \"condition\")),\n class = c(.class, \"rust_condition\", \"simpleCondition\", \"condition\")),\n panic = structure(list(message = .msg, call = .call, kind = \"panic\"),\n class = c(\"rust_error\", \"simpleError\", \"error\", \"condition\")),\n # error / result_err / none_err / conversion / other: an error whose class\n # vector and data (if any) come from the Rust side, e.g. a\n # `Result<T, E: RConditionData>`.\n structure(.cond_fields(list(message = .msg, call = .call, kind = .v$kind)),\n class = c(.class, \"rust_error\", \"simpleError\", \"error\", \"condition\")))\n }\n .c <- .cond(.val)\n switch(.val$kind,\n warning = warning(.c),\n message = message(.c),\n condition = signalCondition(.c),\n stop(.c)\n )\n invisible(NULL)\n}";Expand description
The package preamble already binds the resolver; reuse it there.