effect 3.1.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Equal.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  import type { Equivalence } from "./Equivalence.js"
5
5
  import * as Hash from "./Hash.js"
6
6
  import { hasProperty } from "./Predicate.js"
7
+ import { structuralRegionState } from "./Utils.js"
7
8
 
8
9
  /**
9
10
  * @since 2.0.0
@@ -32,7 +33,7 @@ export function equals(): any {
32
33
  return compareBoth(arguments[0], arguments[1])
33
34
  }
34
35
 
35
- function compareBoth(self: unknown, that: unknown) {
36
+ function compareBoth(self: unknown, that: unknown): boolean {
36
37
  if (self === that) {
37
38
  return true
38
39
  }
@@ -40,16 +41,36 @@ function compareBoth(self: unknown, that: unknown) {
40
41
  if (selfType !== typeof that) {
41
42
  return false
42
43
  }
43
- if (
44
- (selfType === "object" || selfType === "function") &&
45
- self !== null &&
46
- that !== null
47
- ) {
48
- if (isEqual(self) && isEqual(that)) {
49
- return Hash.hash(self) === Hash.hash(that) && self[symbol](that)
44
+ if (selfType === "object" || selfType === "function") {
45
+ if (self !== null && that !== null) {
46
+ if (isEqual(self) && isEqual(that)) {
47
+ return Hash.hash(self) === Hash.hash(that) && self[symbol](that)
48
+ }
49
+ }
50
+ if (structuralRegionState.enabled) {
51
+ if (Array.isArray(self) && Array.isArray(that)) {
52
+ return self.length === that.length && self.every((v, i) => compareBoth(v, that[i]))
53
+ }
54
+ if (Object.getPrototypeOf(self) === Object.prototype && Object.getPrototypeOf(self) === Object.prototype) {
55
+ const keysSelf = Object.keys(self as any)
56
+ const keysThat = Object.keys(that as any)
57
+ if (keysSelf.length === keysThat.length) {
58
+ for (const key of keysSelf) {
59
+ // @ts-expect-error
60
+ if (!(key in that && compareBoth(self[key], that[key]))) {
61
+ return structuralRegionState.tester ? structuralRegionState.tester(self, that) : false
62
+ }
63
+ }
64
+ return true
65
+ }
66
+ }
67
+ return structuralRegionState.tester ? structuralRegionState.tester(self, that) : false
50
68
  }
51
69
  }
52
- return false
70
+
71
+ return structuralRegionState.enabled && structuralRegionState.tester
72
+ ? structuralRegionState.tester(self, that)
73
+ : false
53
74
  }
54
75
 
55
76
  /**
package/src/Hash.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  import { pipe } from "./Function.js"
5
5
  import { globalValue } from "./GlobalValue.js"
6
6
  import { hasProperty } from "./Predicate.js"
7
- import { PCGRandom } from "./Utils.js"
7
+ import { PCGRandom, structuralRegionState } from "./Utils.js"
8
8
 
9
9
  /** @internal */
10
10
  const randomHashCache = globalValue(
@@ -72,6 +72,9 @@ export const hash: <A>(self: A) => number = <A>(self: A) => {
72
72
  * @category hashing
73
73
  */
74
74
  export const random: <A extends object>(self: A) => number = (self) => {
75
+ if (structuralRegionState.enabled === true) {
76
+ return 0
77
+ }
75
78
  if (!randomHashCache.has(self)) {
76
79
  randomHashCache.set(self, number(pcgr.integer(Number.MAX_SAFE_INTEGER)))
77
80
  }
@@ -168,22 +171,36 @@ export const cached: {
168
171
  if (arguments.length === 1) {
169
172
  const self = arguments[0] as object
170
173
  return function(hash: number) {
171
- Object.defineProperty(self, symbol, {
172
- value() {
173
- return hash
174
- },
175
- enumerable: false
176
- })
174
+ // @ts-expect-error
175
+ const original = self[symbol].bind(self)
176
+ if (structuralRegionState.enabled === false) {
177
+ Object.defineProperty(self, symbol, {
178
+ value() {
179
+ if (structuralRegionState.enabled === true) {
180
+ return original()
181
+ }
182
+ return hash
183
+ },
184
+ enumerable: false
185
+ })
186
+ }
177
187
  return hash
178
188
  } as any
179
189
  }
180
190
  const self = arguments[0] as object
181
191
  const hash = arguments[1] as number
182
- Object.defineProperty(self, symbol, {
183
- value() {
184
- return hash
185
- },
186
- enumerable: false
187
- })
192
+ // @ts-expect-error
193
+ const original = self[symbol].bind(self)
194
+ if (structuralRegionState.enabled === false) {
195
+ Object.defineProperty(self, symbol, {
196
+ value() {
197
+ if (structuralRegionState.enabled === true) {
198
+ return original()
199
+ }
200
+ return hash
201
+ },
202
+ enumerable: false
203
+ })
204
+ }
188
205
  return hash
189
206
  }
package/src/Utils.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  * @since 2.0.0
3
3
  */
4
4
  import { identity } from "./Function.js"
5
+ import { globalValue } from "./GlobalValue.js"
5
6
  import type { Kind, TypeLambda } from "./HKT.js"
6
7
  import { getBugErrorMessage } from "./internal/errors.js"
7
8
  import { isNullable, isObject } from "./Predicate.js"
@@ -746,3 +747,40 @@ export function yieldWrapGet<T>(self: YieldWrap<T>): T {
746
747
  }
747
748
  throw new Error(getBugErrorMessage("yieldWrapGet"))
748
749
  }
750
+
751
+ /**
752
+ * Note: this is an experimental feature made available to allow custom matchers in tests, not to be directly used yet in user code
753
+ *
754
+ * @since 3.1.1
755
+ * @status experimental
756
+ * @category modifiers
757
+ */
758
+ export const structuralRegionState = globalValue(
759
+ "effect/Utils/isStructuralRegion",
760
+ (): { enabled: boolean; tester: ((a: unknown, b: unknown) => boolean) | undefined } => ({
761
+ enabled: false,
762
+ tester: undefined
763
+ })
764
+ )
765
+
766
+ /**
767
+ * Note: this is an experimental feature made available to allow custom matchers in tests, not to be directly used yet in user code
768
+ *
769
+ * @since 3.1.1
770
+ * @status experimental
771
+ * @category modifiers
772
+ */
773
+ export const structuralRegion = <A>(body: () => A, tester?: (a: unknown, b: unknown) => boolean): A => {
774
+ const current = structuralRegionState.enabled
775
+ const currentTester = structuralRegionState.tester
776
+ structuralRegionState.enabled = true
777
+ if (tester) {
778
+ structuralRegionState.tester = tester
779
+ }
780
+ try {
781
+ return body()
782
+ } finally {
783
+ structuralRegionState.enabled = current
784
+ structuralRegionState.tester = currentTester
785
+ }
786
+ }
@@ -197,10 +197,18 @@ class EffectPrimitiveFailure {
197
197
  this._tag = _op
198
198
  }
199
199
  [Equal.symbol](this: {}, that: unknown) {
200
- return this === that
200
+ return exitIsExit(that) && that._op === "Failure" &&
201
+ // @ts-expect-error
202
+ Equal.equals(this.effect_instruction_i0, that.effect_instruction_i0)
201
203
  }
202
204
  [Hash.symbol](this: {}) {
203
- return Hash.cached(this, Hash.random(this))
205
+ return pipe(
206
+ // @ts-expect-error
207
+ Hash.string(this._tag),
208
+ // @ts-expect-error
209
+ Hash.combine(Hash.hash(this.effect_instruction_i0)),
210
+ Hash.cached(this)
211
+ )
204
212
  }
205
213
  get cause() {
206
214
  return this.effect_instruction_i0
@@ -238,10 +246,18 @@ class EffectPrimitiveSuccess {
238
246
  this._tag = _op
239
247
  }
240
248
  [Equal.symbol](this: {}, that: unknown) {
241
- return this === that
249
+ return exitIsExit(that) && that._op === "Success" &&
250
+ // @ts-expect-error
251
+ Equal.equals(this.effect_instruction_i0, that.effect_instruction_i0)
242
252
  }
243
253
  [Hash.symbol](this: {}) {
244
- return Hash.cached(this, Hash.random(this))
254
+ return pipe(
255
+ // @ts-expect-error
256
+ Hash.string(this._tag),
257
+ // @ts-expect-error
258
+ Hash.combine(Hash.hash(this.effect_instruction_i0)),
259
+ Hash.cached(this)
260
+ )
245
261
  }
246
262
  get value() {
247
263
  return this.effect_instruction_i0
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.1.0"
1
+ let moduleVersion = "3.1.1"
2
2
 
3
3
  export const getCurrentVersion = () => moduleVersion
4
4