Skip to content

Commit 1757334

Browse files
committed
work with frozen intrinsics
1 parent cfdd411 commit 1757334

File tree

11 files changed

+190
-61
lines changed

11 files changed

+190
-61
lines changed

packages/ai/ai/src/Tool.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,20 @@ function filter(obj: any) {
14991499
return obj
15001500
}
15011501

1502+
// Utility for safely manipulating Error.stackTraceLimit in environments
1503+
// where intrinsics may be frozen (e.g., SES/hardened JavaScript)
1504+
const isStackTraceLimitWritable = (): boolean => {
1505+
const desc = Object.getOwnPropertyDescriptor(Error, "stackTraceLimit")
1506+
if (desc === undefined) {
1507+
return Object.isExtensible(Error)
1508+
}
1509+
return Object.prototype.hasOwnProperty.call(desc, "writable")
1510+
? desc.writable === true
1511+
: desc.set !== undefined
1512+
}
1513+
1514+
const canWriteStackTraceLimit = isStackTraceLimitWritable()
1515+
15021516
/**
15031517
* **Unsafe**: This function will throw an error if an insecure property is
15041518
* found in the parsed JSON or if the provided JSON text is not parseable.
@@ -1508,11 +1522,14 @@ function filter(obj: any) {
15081522
*/
15091523
export const unsafeSecureJsonParse = (text: string): unknown => {
15101524
// Performance optimization, see https://github.com/fastify/secure-json-parse/pull/90
1511-
const { stackTraceLimit } = Error
1525+
if (!canWriteStackTraceLimit) {
1526+
return _parse(text)
1527+
}
1528+
const prevLimit = Error.stackTraceLimit
15121529
Error.stackTraceLimit = 0
15131530
try {
15141531
return _parse(text)
15151532
} finally {
1516-
Error.stackTraceLimit = stackTraceLimit
1533+
Error.stackTraceLimit = prevLimit
15171534
}
15181535
}

packages/effect/src/Effect.ts

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import type {
7373
} from "./Types.js"
7474
import type * as Unify from "./Unify.js"
7575
import { isGeneratorFunction, type YieldWrap } from "./Utils.js"
76+
import { canWriteStackTraceLimit } from "./internal/stackTraceLimit.js"
7677

7778
/**
7879
* @since 2.0.0
@@ -13509,10 +13510,15 @@ export const Tag: <const Id extends string>(id: Id) => <
1350913510
: [X] extends [PromiseLike<infer A>] ? Effect<A, Cause.UnknownException, Self>
1351013511
: Effect<X, never, Self>
1351113512
} = (id) => () => {
13512-
const limit = Error.stackTraceLimit
13513-
Error.stackTraceLimit = 2
13514-
const creationError = new Error()
13515-
Error.stackTraceLimit = limit
13513+
let creationError: Error
13514+
if (!canWriteStackTraceLimit) {
13515+
creationError = new Error()
13516+
} else {
13517+
const prevLimit = Error.stackTraceLimit
13518+
Error.stackTraceLimit = 2
13519+
creationError = new Error()
13520+
Error.stackTraceLimit = prevLimit
13521+
}
1351613522
function TagClass() {}
1351713523
Object.setPrototypeOf(TagClass, TagProto)
1351813524
TagClass.key = id
@@ -13668,10 +13674,15 @@ export const Service: <Self = never>() => [Self] extends [never] ? MissingSelfGe
1366813674
return function() {
1366913675
const [id, maker] = arguments
1367013676
const proxy = "accessors" in maker ? maker["accessors"] : false
13671-
const limit = Error.stackTraceLimit
13672-
Error.stackTraceLimit = 2
13673-
const creationError = new Error()
13674-
Error.stackTraceLimit = limit
13677+
let creationError: Error
13678+
if (!canWriteStackTraceLimit) {
13679+
creationError = new Error()
13680+
} else {
13681+
const prevLimit = Error.stackTraceLimit
13682+
Error.stackTraceLimit = 2
13683+
creationError = new Error()
13684+
Error.stackTraceLimit = prevLimit
13685+
}
1367513686

1367613687
let patchState: "unchecked" | "plain" | "patched" = "unchecked"
1367713688
const TagClass: any = function(this: any, service: any) {
@@ -14628,16 +14639,26 @@ export const fn:
1462814639
name: string,
1462914640
options?: Tracer.SpanOptions
1463014641
) => fn.Gen & fn.NonGen) = function(nameOrBody: Function | string, ...pipeables: Array<any>) {
14631-
const limit = Error.stackTraceLimit
14632-
Error.stackTraceLimit = 2
14633-
const errorDef = new Error()
14634-
Error.stackTraceLimit = limit
14642+
let errorDef: Error
14643+
if (!canWriteStackTraceLimit) {
14644+
errorDef = new Error()
14645+
} else {
14646+
const prevLimit = Error.stackTraceLimit
14647+
Error.stackTraceLimit = 2
14648+
errorDef = new Error()
14649+
Error.stackTraceLimit = prevLimit
14650+
}
1463514651
if (typeof nameOrBody !== "string") {
1463614652
return defineLength(nameOrBody.length, function(this: any, ...args: Array<any>) {
14637-
const limit = Error.stackTraceLimit
14638-
Error.stackTraceLimit = 2
14639-
const errorCall = new Error()
14640-
Error.stackTraceLimit = limit
14653+
let errorCall: Error
14654+
if (!canWriteStackTraceLimit) {
14655+
errorCall = new Error()
14656+
} else {
14657+
const prevLimit = Error.stackTraceLimit
14658+
Error.stackTraceLimit = 2
14659+
errorCall = new Error()
14660+
Error.stackTraceLimit = prevLimit
14661+
}
1464114662
return fnApply({
1464214663
self: this,
1464314664
body: nameOrBody,
@@ -14659,10 +14680,15 @@ export const fn:
1465914680
body.length,
1466014681
({
1466114682
[name](this: any, ...args: Array<any>) {
14662-
const limit = Error.stackTraceLimit
14663-
Error.stackTraceLimit = 2
14664-
const errorCall = new Error()
14665-
Error.stackTraceLimit = limit
14683+
let errorCall: Error
14684+
if (!canWriteStackTraceLimit) {
14685+
errorCall = new Error()
14686+
} else {
14687+
const prevLimit = Error.stackTraceLimit
14688+
Error.stackTraceLimit = 2
14689+
errorCall = new Error()
14690+
Error.stackTraceLimit = prevLimit
14691+
}
1466614692
return fnApply({
1466714693
self: this,
1466814694
body,

packages/effect/src/LayerMap.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import * as RcMap from "./RcMap.js"
1313
import * as Runtime from "./Runtime.js"
1414
import * as Scope from "./Scope.js"
1515
import type { Mutable, NoExcessProperties } from "./Types.js"
16+
import { canWriteStackTraceLimit } from "./internal/stackTraceLimit.js"
1617

1718
/**
1819
* @since 3.14.0
@@ -357,10 +358,15 @@ export const Service = <Self>() =>
357358
Options extends { readonly dependencies: ReadonlyArray<any> } ? Options["dependencies"][number] : never
358359
> => {
359360
const Err = globalThis.Error as any
360-
const limit = Err.stackTraceLimit
361-
Err.stackTraceLimit = 2
362-
const creationError = new Err()
363-
Err.stackTraceLimit = limit
361+
let creationError: Error
362+
if (!canWriteStackTraceLimit) {
363+
creationError = new Err()
364+
} else {
365+
const limit = Err.stackTraceLimit
366+
Err.stackTraceLimit = 2
367+
creationError = new Err()
368+
Err.stackTraceLimit = limit
369+
}
364370

365371
function TagClass() {}
366372
const TagClass_ = TagClass as any as Mutable<TagClass<Self, Id, string, any, any, any, any, any>>

packages/effect/src/Micro.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import type { Stream } from "./Stream.js"
3131
import type { Concurrency, Covariant, Equals, NoExcessProperties, NotFunction, Simplify } from "./Types.js"
3232
import type * as Unify from "./Unify.js"
3333
import { SingleShotGen, YieldWrap, yieldWrapGet } from "./Utils.js"
34+
import { canWriteStackTraceLimit } from "./internal/stackTraceLimit.js"
3435

3536
/**
3637
* @since 3.4.0
@@ -2984,10 +2985,15 @@ export const withTrace: {
29842985
(name: string): <A, E, R>(self: Micro<A, E, R>) => Micro<A, E, R>
29852986
<A, E, R>(self: Micro<A, E, R>, name: string): Micro<A, E, R>
29862987
} = function() {
2987-
const prevLimit = globalThis.Error.stackTraceLimit
2988-
globalThis.Error.stackTraceLimit = 2
2989-
const error = new globalThis.Error()
2990-
globalThis.Error.stackTraceLimit = prevLimit
2988+
let error: globalThis.Error
2989+
if (!canWriteStackTraceLimit) {
2990+
error = new globalThis.Error()
2991+
} else {
2992+
const prevLimit = Error.stackTraceLimit
2993+
Error.stackTraceLimit = 2
2994+
error = new globalThis.Error()
2995+
Error.stackTraceLimit = prevLimit
2996+
}
29912997
function generate(name: string, cause: MicroCause<any>) {
29922998
const stack = error.stack
29932999
if (!stack) {

packages/effect/src/internal/cause.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type { AnySpan, Span } from "../Tracer.js"
1717
import type { NoInfer } from "../Types.js"
1818
import { getBugErrorMessage } from "./errors.js"
1919
import * as OpCodes from "./opCodes/cause.js"
20+
import { canWriteStackTraceLimit } from "./stackTraceLimit.js"
2021

2122
// -----------------------------------------------------------------------------
2223
// Models
@@ -900,8 +901,10 @@ export class PrettyError extends globalThis.Error implements Cause.PrettyError {
900901
span: undefined | Span = undefined
901902
constructor(originalError: unknown) {
902903
const originalErrorIsObject = typeof originalError === "object" && originalError !== null
903-
const prevLimit = Error.stackTraceLimit
904-
Error.stackTraceLimit = 1
904+
const prevLimit = canWriteStackTraceLimit ? Error.stackTraceLimit : undefined
905+
if (canWriteStackTraceLimit) {
906+
Error.stackTraceLimit = 1
907+
}
905908
super(
906909
prettyErrorMessage(originalError),
907910
originalErrorIsObject && "cause" in originalError && typeof originalError.cause !== "undefined"
@@ -911,7 +914,9 @@ export class PrettyError extends globalThis.Error implements Cause.PrettyError {
911914
if (this.message === "") {
912915
this.message = "An error has occurred"
913916
}
914-
Error.stackTraceLimit = prevLimit
917+
if (prevLimit !== undefined) {
918+
Error.stackTraceLimit = prevLimit
919+
}
915920
this.name = originalError instanceof Error ? originalError.name : "Error"
916921
if (originalErrorIsObject) {
917922
if (spanSymbol in originalError) {

packages/effect/src/internal/context.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type * as STM from "../STM.js"
1212
import type { NoInfer } from "../Types.js"
1313
import { EffectPrototype, effectVariance } from "./effectable.js"
1414
import * as option from "./option.js"
15+
import { canWriteStackTraceLimit } from "./stackTraceLimit.js"
1516

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

6869
/** @internal */
6970
export const makeGenericTag = <Identifier, Service = Identifier>(key: string): C.Tag<Identifier, Service> => {
70-
const limit = Error.stackTraceLimit
71-
Error.stackTraceLimit = 2
72-
const creationError = new Error()
73-
Error.stackTraceLimit = limit
71+
let creationError: Error
72+
if (!canWriteStackTraceLimit) {
73+
creationError = new Error()
74+
} else {
75+
const prevLimit = Error.stackTraceLimit
76+
Error.stackTraceLimit = 2
77+
creationError = new Error()
78+
Error.stackTraceLimit = prevLimit
79+
}
7480
const tag = Object.create(TagProto)
7581
Object.defineProperty(tag, "stack", {
7682
get() {
@@ -83,10 +89,15 @@ export const makeGenericTag = <Identifier, Service = Identifier>(key: string): C
8389

8490
/** @internal */
8591
export const Tag = <const Id extends string>(id: Id) => <Self, Shape>(): C.TagClass<Self, Id, Shape> => {
86-
const limit = Error.stackTraceLimit
87-
Error.stackTraceLimit = 2
88-
const creationError = new Error()
89-
Error.stackTraceLimit = limit
92+
let creationError: Error
93+
if (!canWriteStackTraceLimit) {
94+
creationError = new Error()
95+
} else {
96+
const prevLimit = Error.stackTraceLimit
97+
Error.stackTraceLimit = 2
98+
creationError = new Error()
99+
Error.stackTraceLimit = prevLimit
100+
}
90101

91102
function TagClass() {}
92103
Object.setPrototypeOf(TagClass, TagProto)
@@ -104,10 +115,15 @@ export const Reference = <Self>() =>
104115
<const Id extends string, Service>(id: Id, options: {
105116
readonly defaultValue: () => Service
106117
}): C.ReferenceClass<Self, Id, Service> => {
107-
const limit = Error.stackTraceLimit
108-
Error.stackTraceLimit = 2
109-
const creationError = new Error()
110-
Error.stackTraceLimit = limit
118+
let creationError: Error
119+
if (!canWriteStackTraceLimit) {
120+
creationError = new Error()
121+
} else {
122+
const prevLimit = Error.stackTraceLimit
123+
Error.stackTraceLimit = 2
124+
creationError = new Error()
125+
Error.stackTraceLimit = prevLimit
126+
}
111127

112128
function ReferenceClass() {}
113129
Object.setPrototypeOf(ReferenceClass, ReferenceProto)

packages/effect/src/internal/core-effect.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import * as fiberRefsPatch from "./fiberRefs/patch.js"
3838
import type { FiberRuntime } from "./fiberRuntime.js"
3939
import * as metricLabel from "./metric/label.js"
4040
import * as runtimeFlags from "./runtimeFlags.js"
41+
import { canWriteStackTraceLimit } from "./stackTraceLimit.js"
4142
import * as internalTracer from "./tracer.js"
4243

4344
/* @internal */
@@ -2241,10 +2242,15 @@ export const functionWithSpan = <Args extends Array<any>, Ret extends Effect.Eff
22412242
(function(this: any) {
22422243
let captureStackTrace: LazyArg<string | undefined> | boolean = options.captureStackTrace ?? false
22432244
if (options.captureStackTrace !== false) {
2244-
const limit = Error.stackTraceLimit
2245-
Error.stackTraceLimit = 2
2246-
const error = new Error()
2247-
Error.stackTraceLimit = limit
2245+
let error: Error
2246+
if (!canWriteStackTraceLimit) {
2247+
error = new Error()
2248+
} else {
2249+
const prevLimit = Error.stackTraceLimit
2250+
Error.stackTraceLimit = 2
2251+
error = new Error()
2252+
Error.stackTraceLimit = prevLimit
2253+
}
22482254
let cache: false | string = false
22492255
captureStackTrace = () => {
22502256
if (cache !== false) {

packages/effect/src/internal/layer.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import * as OpCodes from "./opCodes/layer.js"
3333
import * as ref from "./ref.js"
3434
import * as runtime from "./runtime.js"
3535
import * as runtimeFlags from "./runtimeFlags.js"
36+
import { canWriteStackTraceLimit } from "./stackTraceLimit.js"
3637
import * as synchronized from "./synchronizedRef.js"
3738
import * as tracer from "./tracer.js"
3839

@@ -693,10 +694,15 @@ const mockImpl = <I, S extends object>(tag: Context.Tag<I, S>, service: Layer.Pa
693694
if (prop in target) {
694695
return target[prop as keyof S]
695696
}
696-
const prevLimit = Error.stackTraceLimit
697-
Error.stackTraceLimit = 2
698-
const error = new Error(`${tag.key}: Unimplemented method "${prop.toString()}"`)
699-
Error.stackTraceLimit = prevLimit
697+
let error: Error
698+
if (!canWriteStackTraceLimit) {
699+
error = new Error(`${tag.key}: Unimplemented method "${prop.toString()}"`)
700+
} else {
701+
const prevLimit = Error.stackTraceLimit
702+
Error.stackTraceLimit = 2
703+
error = new Error(`${tag.key}: Unimplemented method "${prop.toString()}"`)
704+
Error.stackTraceLimit = prevLimit
705+
}
700706
error.name = "UnimplementedError"
701707
return makeUnimplemented(error)
702708
},

packages/effect/src/internal/runtime.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import * as FiberRuntime from "./fiberRuntime.js"
2424
import * as fiberScope from "./fiberScope.js"
2525
import * as OpCodes from "./opCodes/effect.js"
2626
import * as runtimeFlags from "./runtimeFlags.js"
27+
import { canWriteStackTraceLimit } from "./stackTraceLimit.js"
2728
import * as supervisor_ from "./supervisor.js"
2829

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

181182
const asyncFiberException = <A, E>(fiber: Fiber.RuntimeFiber<A, E>): Runtime.AsyncFiberException<A, E> => {
182-
const limit = Error.stackTraceLimit
183+
if (!canWriteStackTraceLimit) {
184+
return new AsyncFiberExceptionImpl(fiber)
185+
}
186+
const prevLimit = Error.stackTraceLimit
183187
Error.stackTraceLimit = 0
184188
const error = new AsyncFiberExceptionImpl(fiber)
185-
Error.stackTraceLimit = limit
189+
Error.stackTraceLimit = prevLimit
186190
return error
187191
}
188192

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

231235
/** @internal */
232236
export const fiberFailure = <E>(cause: Cause.Cause<E>): Runtime.FiberFailure => {
233-
const limit = Error.stackTraceLimit
237+
if (!canWriteStackTraceLimit) {
238+
return new FiberFailureImpl(cause)
239+
}
240+
const prevLimit = Error.stackTraceLimit
234241
Error.stackTraceLimit = 0
235242
const error = new FiberFailureImpl(cause)
236-
Error.stackTraceLimit = limit
243+
Error.stackTraceLimit = prevLimit
237244
return error
238245
}
239246

0 commit comments

Comments
 (0)