-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
138 lines (133 loc) · 4.22 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* @flow */
import hashInteger from "../../hash-functions/integer";
import type Backing from "backing";
import type {Realm} from "../..";
import {$Backing, $Address, $CanBeEmbedded, $CanBeReferenced, $CanContainReferences} from "../../symbols";
export function make (realm: Realm): PrimitiveType<any> {
const {PrimitiveType} = realm;
const Any = new PrimitiveType({
name: 'Any',
byteAlignment: 8,
byteLength: 12,
cast (input: any): any {
// @flowIssue 252
if (typeof input === 'function' || typeof input === 'symbol') {
throw new TypeError(`Cannot store values with type: ${typeof input}`);
}
else if (input === undefined) {
return null;
}
else {
return input;
}
},
accepts (input: any): boolean {
// @flowIssue 252
if (typeof input === 'function' || typeof input === 'symbol') {
return false;
}
else {
return true;
}
},
initialize (backing: Backing, address: float64, initialValue: any): void {
const Type = realm.typeOf(initialValue);
let initialAddress;
if (Type == null) {
backing.setFloat64(address, 0);
backing.setUint32(address + 8, 0);
}
else if (Type.byteLength <= 8) {
Type.initialize(backing, address, initialValue);
backing.setUint32(address + 8, Type.id);
}
else if (initialValue[$Backing] === backing && (initialAddress = initialValue[$Address])) {
backing.setFloat64(address, initialAddress);
backing.setUint32(address + 8, Type.id);
backing.gc.ref(initialAddress);
}
else {
const target = backing.gc.alloc(Type.byteLength, Type.id, 1);
Type.initialize(backing, target, initialValue);
backing.setFloat64(address, target);
backing.setUint32(address + 8, Type.id);
}
},
store (backing: Backing, address: float64, value: any): void {
const Type = realm.typeOf(value);
const existingTypeId = backing.getUint32(address + 8);
if (existingTypeId !== 0) {
const existingType = realm.I[existingTypeId];
if (Type != null && existingType === Type && Type.byteLength <= 8) {
Type.store(backing, address, value);
return; // nothing left to do.
}
else if (existingType.byteLength <= 8) {
existingType.clear(backing, address);
}
else {
const pointer = backing.getFloat64(address);
if (pointer !== 0) {
backing.gc.unref(pointer);
backing.setFloat64(address, 0); // ensures that the value is cleared, even if store fails.
}
}
}
let valueAddress;
if (Type == null) {
backing.setFloat64(address, 0);
backing.setUint32(address + 8, 0);
}
else if (Type.byteLength <= 8) {
Type.initialize(backing, address, value);
backing.setUint32(address + 8, Type.id);
}
else if (value[$Backing] === backing && (valueAddress = value[$Address])) {
backing.setFloat64(address, valueAddress);
backing.setUint32(address + 8, Type.id);
backing.gc.ref(valueAddress);
}
else {
const target = backing.gc.alloc(Type.byteLength, Type.id, 1);
Type.initialize(backing, target, value);
backing.setFloat64(address, target);
backing.setUint32(address + 8, Type.id);
}
},
load (backing: Backing, address: float64): any {
const typeId = backing.getUint32(address + 8);
if (typeId === 0) {
return null;
}
const Type = realm.I[typeId];
if (Type.byteLength <= 8) {
return Type.load(backing, address);
}
const pointer = backing.getFloat64(address);
assert: pointer > 0;
return Type.load(backing, pointer);
},
emptyValue (): any {
return null;
},
randomValue (): any {
return null;
},
hashValue (input): uint32 {
const Type = realm.typeOf(input);
if (Type == null) {
return 4;
}
else {
return Type.hashValue(input);
}
},
flowType () {
return `any`;
}
});
Any[$CanBeEmbedded] = true;
Any[$CanContainReferences] = true;
Any[$CanBeReferenced] = false;
return Any;
}