Skip to content
Open
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
21 changes: 19 additions & 2 deletions packages/ai/ai/src/Tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,20 @@ function filter(obj: any) {
return obj
}

// Utility for safely manipulating Error.stackTraceLimit in environments
// where intrinsics may be frozen (e.g., SES/hardened JavaScript)
const isStackTraceLimitWritable = (): boolean => {
const desc = Object.getOwnPropertyDescriptor(Error, "stackTraceLimit")
if (desc === undefined) {
return Object.isExtensible(Error)
}
return Object.prototype.hasOwnProperty.call(desc, "writable")
? desc.writable === true
: desc.set !== undefined
}

const canWriteStackTraceLimit = isStackTraceLimitWritable()

/**
* **Unsafe**: This function will throw an error if an insecure property is
* found in the parsed JSON or if the provided JSON text is not parseable.
Expand All @@ -1508,11 +1522,14 @@ function filter(obj: any) {
*/
export const unsafeSecureJsonParse = (text: string): unknown => {
// Performance optimization, see https://github.com/fastify/secure-json-parse/pull/90
const { stackTraceLimit } = Error
if (!canWriteStackTraceLimit) {
return _parse(text)
}
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 0
try {
return _parse(text)
} finally {
Error.stackTraceLimit = stackTraceLimit
Error.stackTraceLimit = prevLimit
}
}
66 changes: 46 additions & 20 deletions packages/effect/src/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import type {
} from "./Types.js"
import type * as Unify from "./Unify.js"
import { isGeneratorFunction, type YieldWrap } from "./Utils.js"
import { canWriteStackTraceLimit } from "./internal/stackTraceLimit.js"

/**
* @since 2.0.0
Expand Down Expand Up @@ -13509,10 +13510,15 @@ export const Tag: <const Id extends string>(id: Id) => <
: [X] extends [PromiseLike<infer A>] ? Effect<A, Cause.UnknownException, Self>
: Effect<X, never, Self>
} = (id) => () => {
const limit = Error.stackTraceLimit
Error.stackTraceLimit = 2
const creationError = new Error()
Error.stackTraceLimit = limit
let creationError: Error
if (!canWriteStackTraceLimit) {
creationError = new Error()
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
creationError = new Error()
Error.stackTraceLimit = prevLimit
}
function TagClass() {}
Object.setPrototypeOf(TagClass, TagProto)
TagClass.key = id
Expand Down Expand Up @@ -13668,10 +13674,15 @@ export const Service: <Self = never>() => [Self] extends [never] ? MissingSelfGe
return function() {
const [id, maker] = arguments
const proxy = "accessors" in maker ? maker["accessors"] : false
const limit = Error.stackTraceLimit
Error.stackTraceLimit = 2
const creationError = new Error()
Error.stackTraceLimit = limit
let creationError: Error
if (!canWriteStackTraceLimit) {
creationError = new Error()
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
creationError = new Error()
Error.stackTraceLimit = prevLimit
}

let patchState: "unchecked" | "plain" | "patched" = "unchecked"
const TagClass: any = function(this: any, service: any) {
Expand Down Expand Up @@ -14628,16 +14639,26 @@ export const fn:
name: string,
options?: Tracer.SpanOptions
) => fn.Gen & fn.NonGen) = function(nameOrBody: Function | string, ...pipeables: Array<any>) {
const limit = Error.stackTraceLimit
Error.stackTraceLimit = 2
const errorDef = new Error()
Error.stackTraceLimit = limit
let errorDef: Error
if (!canWriteStackTraceLimit) {
errorDef = new Error()
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
errorDef = new Error()
Error.stackTraceLimit = prevLimit
}
if (typeof nameOrBody !== "string") {
return defineLength(nameOrBody.length, function(this: any, ...args: Array<any>) {
const limit = Error.stackTraceLimit
Error.stackTraceLimit = 2
const errorCall = new Error()
Error.stackTraceLimit = limit
let errorCall: Error
if (!canWriteStackTraceLimit) {
errorCall = new Error()
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
errorCall = new Error()
Error.stackTraceLimit = prevLimit
}
return fnApply({
self: this,
body: nameOrBody,
Expand All @@ -14659,10 +14680,15 @@ export const fn:
body.length,
({
[name](this: any, ...args: Array<any>) {
const limit = Error.stackTraceLimit
Error.stackTraceLimit = 2
const errorCall = new Error()
Error.stackTraceLimit = limit
let errorCall: Error
if (!canWriteStackTraceLimit) {
errorCall = new Error()
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
errorCall = new Error()
Error.stackTraceLimit = prevLimit
}
return fnApply({
self: this,
body,
Expand Down
14 changes: 10 additions & 4 deletions packages/effect/src/LayerMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as RcMap from "./RcMap.js"
import * as Runtime from "./Runtime.js"
import * as Scope from "./Scope.js"
import type { Mutable, NoExcessProperties } from "./Types.js"
import { canWriteStackTraceLimit } from "./internal/stackTraceLimit.js"

/**
* @since 3.14.0
Expand Down Expand Up @@ -357,10 +358,15 @@ export const Service = <Self>() =>
Options extends { readonly dependencies: ReadonlyArray<any> } ? Options["dependencies"][number] : never
> => {
const Err = globalThis.Error as any
const limit = Err.stackTraceLimit
Err.stackTraceLimit = 2
const creationError = new Err()
Err.stackTraceLimit = limit
let creationError: Error
if (!canWriteStackTraceLimit) {
creationError = new Err()
} else {
const limit = Err.stackTraceLimit
Err.stackTraceLimit = 2
creationError = new Err()
Err.stackTraceLimit = limit
}

function TagClass() {}
const TagClass_ = TagClass as any as Mutable<TagClass<Self, Id, string, any, any, any, any, any>>
Expand Down
14 changes: 10 additions & 4 deletions packages/effect/src/Micro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import type { Stream } from "./Stream.js"
import type { Concurrency, Covariant, Equals, NoExcessProperties, NotFunction, Simplify } from "./Types.js"
import type * as Unify from "./Unify.js"
import { SingleShotGen, YieldWrap, yieldWrapGet } from "./Utils.js"
import { canWriteStackTraceLimit } from "./internal/stackTraceLimit.js"

/**
* @since 3.4.0
Expand Down Expand Up @@ -2984,10 +2985,15 @@ export const withTrace: {
(name: string): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E, R>
<A, E, R>(self: Micro<A, E, R>, name: string): Micro<A, E, R>
} = function() {
const prevLimit = globalThis.Error.stackTraceLimit
globalThis.Error.stackTraceLimit = 2
const error = new globalThis.Error()
globalThis.Error.stackTraceLimit = prevLimit
let error: globalThis.Error
if (!canWriteStackTraceLimit) {
error = new globalThis.Error()
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
error = new globalThis.Error()
Error.stackTraceLimit = prevLimit
}
function generate(name: string, cause: MicroCause<any>) {
const stack = error.stack
if (!stack) {
Expand Down
11 changes: 8 additions & 3 deletions packages/effect/src/internal/cause.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type { AnySpan, Span } from "../Tracer.js"
import type { NoInfer } from "../Types.js"
import { getBugErrorMessage } from "./errors.js"
import * as OpCodes from "./opCodes/cause.js"
import { canWriteStackTraceLimit } from "./stackTraceLimit.js"

// -----------------------------------------------------------------------------
// Models
Expand Down Expand Up @@ -900,8 +901,10 @@ export class PrettyError extends globalThis.Error implements Cause.PrettyError {
span: undefined | Span = undefined
constructor(originalError: unknown) {
const originalErrorIsObject = typeof originalError === "object" && originalError !== null
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 1
const prevLimit = canWriteStackTraceLimit ? Error.stackTraceLimit : undefined
if (canWriteStackTraceLimit) {
Error.stackTraceLimit = 1
}
super(
prettyErrorMessage(originalError),
originalErrorIsObject && "cause" in originalError && typeof originalError.cause !== "undefined"
Expand All @@ -911,7 +914,9 @@ export class PrettyError extends globalThis.Error implements Cause.PrettyError {
if (this.message === "") {
this.message = "An error has occurred"
}
Error.stackTraceLimit = prevLimit
if (prevLimit !== undefined) {
Error.stackTraceLimit = prevLimit
}
this.name = originalError instanceof Error ? originalError.name : "Error"
if (originalErrorIsObject) {
if (spanSymbol in originalError) {
Expand Down
40 changes: 28 additions & 12 deletions packages/effect/src/internal/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type * as STM from "../STM.js"
import type { NoInfer } from "../Types.js"
import { EffectPrototype, effectVariance } from "./effectable.js"
import * as option from "./option.js"
import { canWriteStackTraceLimit } from "./stackTraceLimit.js"

/** @internal */
export const TagTypeId: C.TagTypeId = Symbol.for("effect/Context/Tag") as C.TagTypeId
Expand Down Expand Up @@ -67,10 +68,15 @@ export const ReferenceProto: any = {

/** @internal */
export const makeGenericTag = <Identifier, Service = Identifier>(key: string): C.Tag<Identifier, Service> => {
const limit = Error.stackTraceLimit
Error.stackTraceLimit = 2
const creationError = new Error()
Error.stackTraceLimit = limit
let creationError: Error
if (!canWriteStackTraceLimit) {
creationError = new Error()
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
creationError = new Error()
Error.stackTraceLimit = prevLimit
}
const tag = Object.create(TagProto)
Object.defineProperty(tag, "stack", {
get() {
Expand All @@ -83,10 +89,15 @@ export const makeGenericTag = <Identifier, Service = Identifier>(key: string): C

/** @internal */
export const Tag = <const Id extends string>(id: Id) => <Self, Shape>(): C.TagClass<Self, Id, Shape> => {
const limit = Error.stackTraceLimit
Error.stackTraceLimit = 2
const creationError = new Error()
Error.stackTraceLimit = limit
let creationError: Error
if (!canWriteStackTraceLimit) {
creationError = new Error()
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
creationError = new Error()
Error.stackTraceLimit = prevLimit
}

function TagClass() {}
Object.setPrototypeOf(TagClass, TagProto)
Expand All @@ -104,10 +115,15 @@ export const Reference = <Self>() =>
<const Id extends string, Service>(id: Id, options: {
readonly defaultValue: () => Service
}): C.ReferenceClass<Self, Id, Service> => {
const limit = Error.stackTraceLimit
Error.stackTraceLimit = 2
const creationError = new Error()
Error.stackTraceLimit = limit
let creationError: Error
if (!canWriteStackTraceLimit) {
creationError = new Error()
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
creationError = new Error()
Error.stackTraceLimit = prevLimit
}

function ReferenceClass() {}
Object.setPrototypeOf(ReferenceClass, ReferenceProto)
Expand Down
14 changes: 10 additions & 4 deletions packages/effect/src/internal/core-effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import * as fiberRefsPatch from "./fiberRefs/patch.js"
import type { FiberRuntime } from "./fiberRuntime.js"
import * as metricLabel from "./metric/label.js"
import * as runtimeFlags from "./runtimeFlags.js"
import { canWriteStackTraceLimit } from "./stackTraceLimit.js"
import * as internalTracer from "./tracer.js"

/* @internal */
Expand Down Expand Up @@ -2241,10 +2242,15 @@ export const functionWithSpan = <Args extends Array<any>, Ret extends Effect.Eff
(function(this: any) {
let captureStackTrace: LazyArg<string | undefined> | boolean = options.captureStackTrace ?? false
if (options.captureStackTrace !== false) {
const limit = Error.stackTraceLimit
Error.stackTraceLimit = 2
const error = new Error()
Error.stackTraceLimit = limit
let error: Error
if (!canWriteStackTraceLimit) {
error = new Error()
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
error = new Error()
Error.stackTraceLimit = prevLimit
}
let cache: false | string = false
captureStackTrace = () => {
if (cache !== false) {
Expand Down
14 changes: 10 additions & 4 deletions packages/effect/src/internal/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import * as OpCodes from "./opCodes/layer.js"
import * as ref from "./ref.js"
import * as runtime from "./runtime.js"
import * as runtimeFlags from "./runtimeFlags.js"
import { canWriteStackTraceLimit } from "./stackTraceLimit.js"
import * as synchronized from "./synchronizedRef.js"
import * as tracer from "./tracer.js"

Expand Down Expand Up @@ -693,10 +694,15 @@ const mockImpl = <I, S extends object>(tag: Context.Tag<I, S>, service: Layer.Pa
if (prop in target) {
return target[prop as keyof S]
}
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
const error = new Error(`${tag.key}: Unimplemented method "${prop.toString()}"`)
Error.stackTraceLimit = prevLimit
let error: Error
if (!canWriteStackTraceLimit) {
error = new Error(`${tag.key}: Unimplemented method "${prop.toString()}"`)
} else {
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 2
error = new Error(`${tag.key}: Unimplemented method "${prop.toString()}"`)
Error.stackTraceLimit = prevLimit
}
error.name = "UnimplementedError"
return makeUnimplemented(error)
},
Expand Down
15 changes: 11 additions & 4 deletions packages/effect/src/internal/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import * as FiberRuntime from "./fiberRuntime.js"
import * as fiberScope from "./fiberScope.js"
import * as OpCodes from "./opCodes/effect.js"
import * as runtimeFlags from "./runtimeFlags.js"
import { canWriteStackTraceLimit } from "./stackTraceLimit.js"
import * as supervisor_ from "./supervisor.js"

const makeDual = <Args extends Array<any>, Return>(
Expand Down Expand Up @@ -179,10 +180,13 @@ class AsyncFiberExceptionImpl<A, E = never> extends Error implements Runtime.Asy
}

const asyncFiberException = <A, E>(fiber: Fiber.RuntimeFiber<A, E>): Runtime.AsyncFiberException<A, E> => {
const limit = Error.stackTraceLimit
if (!canWriteStackTraceLimit) {
return new AsyncFiberExceptionImpl(fiber)
}
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 0
const error = new AsyncFiberExceptionImpl(fiber)
Error.stackTraceLimit = limit
Error.stackTraceLimit = prevLimit
return error
}

Expand Down Expand Up @@ -230,10 +234,13 @@ class FiberFailureImpl extends Error implements Runtime.FiberFailure {

/** @internal */
export const fiberFailure = <E>(cause: Cause.Cause<E>): Runtime.FiberFailure => {
const limit = Error.stackTraceLimit
if (!canWriteStackTraceLimit) {
return new FiberFailureImpl(cause)
}
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 0
const error = new FiberFailureImpl(cause)
Error.stackTraceLimit = limit
Error.stackTraceLimit = prevLimit
return error
}

Expand Down
Loading