1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.default = void 0;
|
7 |
|
8 | var _index = require("../domains/index.js");
|
9 |
|
10 | var _errors = require("../errors.js");
|
11 |
|
12 | var _index2 = require("./index.js");
|
13 |
|
14 | var _utils = require("../react/utils.js");
|
15 |
|
16 | var _builder = _interopRequireDefault(require("../utils/builder.js"));
|
17 |
|
18 | var _index3 = require("../methods/index.js");
|
19 |
|
20 | var _singletons = require("../singletons.js");
|
21 |
|
22 | var _invariant = _interopRequireDefault(require("../invariant.js"));
|
23 |
|
24 | var _generator = require("../utils/generator.js");
|
25 |
|
26 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
27 |
|
28 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
29 |
|
30 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
31 |
|
32 | function isWidenedValue(v) {
|
33 | if (!(v instanceof _index2.AbstractValue)) return false;
|
34 | if (v.kind === "widened" || v.kind === "widened property") return true;
|
35 |
|
36 | for (let a of v.args) {
|
37 | if (isWidenedValue(a)) return true;
|
38 | }
|
39 |
|
40 | return false;
|
41 | }
|
42 |
|
43 | const lengthTemplateSrc = "(A).length";
|
44 | const lengthTemplate = (0, _builder.default)(lengthTemplateSrc);
|
45 |
|
46 | class ObjectValue extends _index2.ConcreteValue {
|
47 | constructor(realm, proto, intrinsicName, refuseSerialization = false) {
|
48 | super(realm, intrinsicName);
|
49 | realm.recordNewObject(this);
|
50 | if (realm.useAbstractInterpretation) this.setupBindings(this.getTrackedPropertyNames());
|
51 | this.$Prototype = proto || realm.intrinsics.null;
|
52 | this.$Extensible = realm.intrinsics.true;
|
53 | this._isPartial = realm.intrinsics.false;
|
54 | this._isHavoced = realm.intrinsics.false;
|
55 | this._isSimple = realm.intrinsics.false;
|
56 | this._simplicityIsTransitive = realm.intrinsics.false;
|
57 | this._isFinal = realm.intrinsics.false;
|
58 | this.properties = new Map();
|
59 | this.symbols = new Map();
|
60 | this.refuseSerialization = refuseSerialization;
|
61 |
|
62 |
|
63 |
|
64 | this.$IsClassPrototype = false;
|
65 | }
|
66 |
|
67 | getTrackedPropertyNames() {
|
68 | return ObjectValue.trackedPropertyNames;
|
69 | }
|
70 |
|
71 | setupBindings(propertyNames) {
|
72 | for (let propName of propertyNames) {
|
73 | let propBindingName = ObjectValue.trackedPropertyBindingNames.get(propName);
|
74 | (0, _invariant.default)(propBindingName !== undefined);
|
75 | this[propBindingName] = undefined;
|
76 | }
|
77 | }
|
78 |
|
79 | static setupTrackedPropertyAccessors(propertyNames) {
|
80 | for (let propName of propertyNames) {
|
81 | let propBindingName = ObjectValue.trackedPropertyBindingNames.get(propName);
|
82 | if (propBindingName === undefined) ObjectValue.trackedPropertyBindingNames.set(propName, propBindingName = propName + "_binding");
|
83 | Object.defineProperty(ObjectValue.prototype, propName, {
|
84 | configurable: true,
|
85 | get: function () {
|
86 | let binding = this[propBindingName];
|
87 | return binding === undefined ? undefined : binding.descriptor.value;
|
88 | },
|
89 | set: function (v) {
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 | (0, _invariant.default)(
|
98 | this.$IsClassPrototype === undefined ||
|
99 | this.mightNotBeHavocedObject() ||
|
100 |
|
101 |
|
102 |
|
103 | propBindingName === "_isPartial_binding", "cannot mutate a havoced object");
|
104 | let binding = this[propBindingName];
|
105 |
|
106 | if (binding === undefined) {
|
107 | let desc = {
|
108 | writeable: true,
|
109 | value: undefined
|
110 | };
|
111 | this[propBindingName] = binding = {
|
112 | descriptor: desc,
|
113 | object: this,
|
114 | key: propName,
|
115 | internalSlot: true
|
116 | };
|
117 | }
|
118 |
|
119 | this.$Realm.recordModifiedProperty(binding);
|
120 | binding.descriptor.value = v;
|
121 | }
|
122 | });
|
123 | }
|
124 | }
|
125 |
|
126 | equals(x) {
|
127 | return this === x;
|
128 | }
|
129 |
|
130 | getHash() {
|
131 | if (!this.hashValue) {
|
132 | this.hashValue = ++this.$Realm.objectCount;
|
133 | }
|
134 |
|
135 | return this.hashValue;
|
136 | }
|
137 |
|
138 | get temporalAlias() {
|
139 | return this._temporalAlias;
|
140 | }
|
141 |
|
142 | set temporalAlias(value) {
|
143 | this._temporalAlias = value;
|
144 | }
|
145 |
|
146 | hasStringOrSymbolProperties() {
|
147 | for (let prop of this.properties.values()) {
|
148 | if (prop.descriptor === undefined) continue;
|
149 | return true;
|
150 | }
|
151 |
|
152 | for (let prop of this.symbols.values()) {
|
153 | if (prop.descriptor === undefined) continue;
|
154 | return true;
|
155 | }
|
156 |
|
157 | return false;
|
158 | }
|
159 |
|
160 | mightBeFalse() {
|
161 | return false;
|
162 | }
|
163 |
|
164 | mightNotBeObject() {
|
165 | return false;
|
166 | }
|
167 |
|
168 | throwIfNotObject() {
|
169 | return this;
|
170 | }
|
171 |
|
172 | makeNotPartial() {
|
173 | this._isPartial = this.$Realm.intrinsics.false;
|
174 | }
|
175 |
|
176 | makePartial() {
|
177 | this._isPartial = this.$Realm.intrinsics.true;
|
178 | }
|
179 |
|
180 | makeSimple(option) {
|
181 | this._isSimple = this.$Realm.intrinsics.true;
|
182 | this._simplicityIsTransitive = new _index2.BooleanValue(this.$Realm, option === "transitive" || option instanceof _index2.StringValue && option.value === "transitive");
|
183 | }
|
184 |
|
185 | makeFinal() {
|
186 | this._isFinal = this.$Realm.intrinsics.true;
|
187 | }
|
188 |
|
189 | makeNotFinal() {
|
190 | this._isFinal = this.$Realm.intrinsics.false;
|
191 | }
|
192 |
|
193 | isPartialObject() {
|
194 | return this._isPartial.mightBeTrue();
|
195 | }
|
196 |
|
197 | mightBeFinalObject() {
|
198 | return this._isFinal.mightBeTrue();
|
199 | }
|
200 |
|
201 | mightNotBeFinalObject() {
|
202 | return this._isFinal.mightNotBeTrue();
|
203 | }
|
204 |
|
205 | havoc() {
|
206 | this._isHavoced = this.$Realm.intrinsics.true;
|
207 | }
|
208 |
|
209 | mightBeHavocedObject() {
|
210 | return this._isHavoced.mightBeTrue();
|
211 | }
|
212 |
|
213 | mightNotBeHavocedObject() {
|
214 | return this._isHavoced.mightNotBeTrue();
|
215 | }
|
216 |
|
217 | isSimpleObject() {
|
218 | if (!this._isSimple.mightNotBeTrue()) return true;
|
219 | if (this.isPartialObject()) return false;
|
220 | if (this.symbols.size > 0) return false;
|
221 |
|
222 | for (let propertyBinding of this.properties.values()) {
|
223 | let desc = propertyBinding.descriptor;
|
224 | if (desc === undefined) continue;
|
225 |
|
226 | if (!(0, _index3.IsDataDescriptor)(this.$Realm, desc)) return false;
|
227 | if (!desc.writable) return false;
|
228 | }
|
229 |
|
230 | if (this.$Prototype instanceof _index2.NullValue) return true;
|
231 | if (this.$Prototype === this.$Realm.intrinsics.ObjectPrototype) return true;
|
232 | (0, _invariant.default)(this.$Prototype);
|
233 | return this.$Prototype.isSimpleObject();
|
234 | }
|
235 |
|
236 | isTransitivelySimple() {
|
237 | return !this._simplicityIsTransitive.mightNotBeTrue();
|
238 | }
|
239 |
|
240 | getExtensible() {
|
241 | return this.$Extensible.throwIfNotConcreteBoolean().value;
|
242 | }
|
243 |
|
244 | setExtensible(v) {
|
245 | this.$Extensible = v ? this.$Realm.intrinsics.true : this.$Realm.intrinsics.false;
|
246 | }
|
247 |
|
248 | getKind() {
|
249 |
|
250 | if (this.$SymbolData !== undefined) return "Symbol";
|
251 | if (this.$StringData !== undefined) return "String";
|
252 | if (this.$NumberData !== undefined) return "Number";
|
253 | if (this.$BooleanData !== undefined) return "Boolean";
|
254 | if (this.$DateValue !== undefined) return "Date";
|
255 | if (this.$RegExpMatcher !== undefined) return "RegExp";
|
256 | if (this.$SetData !== undefined) return "Set";
|
257 | if (this.$MapData !== undefined) return "Map";
|
258 | if (this.$DataView !== undefined) return "DataView";
|
259 | if (this.$ArrayBufferData !== undefined) return "ArrayBuffer";
|
260 | if (this.$WeakMapData !== undefined) return "WeakMap";
|
261 | if (this.$WeakSetData !== undefined) return "WeakSet";
|
262 | if ((0, _utils.isReactElement)(this) && this.$Realm.react.enabled) return "ReactElement";
|
263 | if (this.$TypedArrayName !== undefined) return this.$TypedArrayName;
|
264 |
|
265 | return "Object";
|
266 | }
|
267 |
|
268 | defineNativeMethod(name, length, callback, desc = {}) {
|
269 | let intrinsicName;
|
270 |
|
271 | if (typeof name === "string") {
|
272 | if (this.intrinsicName) intrinsicName = `${this.intrinsicName}.${name}`;
|
273 | } else if (name instanceof _index2.SymbolValue) {
|
274 | if (this.intrinsicName && name.intrinsicName) intrinsicName = `${this.intrinsicName}[${name.intrinsicName}]`;
|
275 | } else {
|
276 | (0, _invariant.default)(false);
|
277 | }
|
278 |
|
279 | let fnValue = new _index2.NativeFunctionValue(this.$Realm, intrinsicName, name, length, callback, false);
|
280 | this.defineNativeProperty(name, fnValue, desc);
|
281 | return fnValue;
|
282 | }
|
283 |
|
284 | defineNativeProperty(name, value, desc = {}) {
|
285 | (0, _invariant.default)(!value || value instanceof _index2.Value);
|
286 | this.$DefineOwnProperty(name, _objectSpread({
|
287 | value,
|
288 | writable: true,
|
289 | enumerable: false,
|
290 | configurable: true
|
291 | }, desc));
|
292 | }
|
293 |
|
294 | defineNativeGetter(name, callback, desc = {}) {
|
295 | let intrinsicName, funcName;
|
296 |
|
297 | if (typeof name === "string") {
|
298 | funcName = `get ${name}`;
|
299 | if (this.intrinsicName) intrinsicName = `${this.intrinsicName}.${name}`;
|
300 | } else if (name instanceof _index2.SymbolValue) {
|
301 | funcName = name.$Description instanceof _index2.Value ? `get [${name.$Description.throwIfNotConcreteString().value}]` : `get [${"?"}]`;
|
302 | if (this.intrinsicName && name.intrinsicName) intrinsicName = `${this.intrinsicName}[${name.intrinsicName}]`;
|
303 | } else {
|
304 | (0, _invariant.default)(false);
|
305 | }
|
306 |
|
307 | let func = new _index2.NativeFunctionValue(this.$Realm, intrinsicName, funcName, 0, callback);
|
308 | this.$DefineOwnProperty(name, _objectSpread({
|
309 | get: func,
|
310 | set: this.$Realm.intrinsics.undefined,
|
311 | enumerable: false,
|
312 | configurable: true
|
313 | }, desc));
|
314 | }
|
315 |
|
316 | defineNativeConstant(name, value, desc = {}) {
|
317 | (0, _invariant.default)(!value || value instanceof _index2.Value);
|
318 | this.$DefineOwnProperty(name, _objectSpread({
|
319 | value,
|
320 | writable: false,
|
321 | enumerable: false,
|
322 | configurable: false
|
323 | }, desc));
|
324 | }
|
325 |
|
326 | getOwnPropertyKeysArray(allowAbstractKeys = false) {
|
327 | if (this.isPartialObject() || this.mightBeHavocedObject() || this.unknownProperty !== undefined) {
|
328 | _index2.AbstractValue.reportIntrospectionError(this);
|
329 |
|
330 | throw new _errors.FatalError();
|
331 | }
|
332 |
|
333 | let keyArray = Array.from(this.properties.keys());
|
334 | keyArray = keyArray.filter(x => {
|
335 | let pb = this.properties.get(x);
|
336 | if (!pb || pb.descriptor === undefined) return false;
|
337 | let pv = pb.descriptor.value;
|
338 | if (pv === undefined) return true;
|
339 | (0, _invariant.default)(pv instanceof _index2.Value);
|
340 | if (!pv.mightHaveBeenDeleted()) return true;
|
341 |
|
342 |
|
343 |
|
344 |
|
345 | (0, _invariant.default)(pv instanceof _index2.AbstractValue);
|
346 | if (allowAbstractKeys) return true;
|
347 |
|
348 | _index2.AbstractValue.reportIntrospectionError(pv);
|
349 |
|
350 | throw new _errors.FatalError();
|
351 | });
|
352 | this.$Realm.callReportObjectGetOwnProperties(this);
|
353 | return keyArray;
|
354 | }
|
355 |
|
356 |
|
357 | getSnapshot(options) {
|
358 | try {
|
359 | if (this.temporalAlias !== undefined) return this.temporalAlias;
|
360 | (0, _invariant.default)(!this.isPartialObject());
|
361 | let template = new ObjectValue(this.$Realm, this.$Realm.intrinsics.ObjectPrototype);
|
362 | this.copyKeys(this.$OwnPropertyKeys(), this, template);
|
363 | let realm = this.$Realm;
|
364 |
|
365 | template.makeFinal();
|
366 |
|
367 |
|
368 | if (realm.react.enabled && realm.react.reactProps.has(this)) {
|
369 | realm.react.reactProps.add(template);
|
370 | }
|
371 |
|
372 | let operationDescriptor = (0, _generator.createOperationDescriptor)("SINGLE_ARG");
|
373 |
|
374 | let result = _index2.AbstractValue.createTemporalFromBuildFunction(this.$Realm, ObjectValue, [template], operationDescriptor, {
|
375 | skipInvariant: true,
|
376 | isPure: true
|
377 | });
|
378 |
|
379 | (0, _invariant.default)(result instanceof _index2.AbstractObjectValue);
|
380 | result.values = new _index.ValuesDomain(template);
|
381 | return result;
|
382 | } finally {
|
383 | if (options && options.removeProperties) {
|
384 | this.properties = new Map();
|
385 | this.symbols = new Map();
|
386 | this.unknownProperty = undefined;
|
387 | }
|
388 | }
|
389 | }
|
390 |
|
391 | copyKeys(keys, from, to) {
|
392 |
|
393 | for (let nextKey of keys) {
|
394 |
|
395 | let desc = from.$GetOwnProperty(nextKey);
|
396 |
|
397 | if (desc && desc.enumerable) {
|
398 | _singletons.Properties.ThrowIfMightHaveBeenDeleted(desc.value);
|
399 |
|
400 |
|
401 | let propValue = (0, _index3.Get)(this.$Realm, from, nextKey);
|
402 |
|
403 | _singletons.Properties.Set(this.$Realm, to, nextKey, propValue, true);
|
404 | }
|
405 | }
|
406 | }
|
407 |
|
408 | _serialize(set, stack) {
|
409 | let obj = set({});
|
410 |
|
411 | for (let [key, propertyBinding] of this.properties) {
|
412 | let desc = propertyBinding.descriptor;
|
413 | if (desc === undefined) continue;
|
414 |
|
415 | _singletons.Properties.ThrowIfMightHaveBeenDeleted(desc.value);
|
416 |
|
417 | let serializedDesc = {
|
418 | enumerable: desc.enumerable,
|
419 | configurable: desc.configurable
|
420 | };
|
421 |
|
422 | if (desc.value) {
|
423 | serializedDesc.writable = desc.writable;
|
424 | (0, _invariant.default)(desc.value instanceof _index2.Value);
|
425 | serializedDesc.value = desc.value.serialize(stack);
|
426 | } else {
|
427 | (0, _invariant.default)(desc.get !== undefined);
|
428 | serializedDesc.get = desc.get.serialize(stack);
|
429 | (0, _invariant.default)(desc.set !== undefined);
|
430 | serializedDesc.set = desc.set.serialize(stack);
|
431 | }
|
432 |
|
433 | Object.defineProperty(obj, key, serializedDesc);
|
434 | }
|
435 |
|
436 | return obj;
|
437 | }
|
438 |
|
439 |
|
440 |
|
441 |
|
442 | usesOrdinaryObjectInternalPrototypeMethods() {
|
443 | return true;
|
444 | }
|
445 |
|
446 |
|
447 | $GetPrototypeOf() {
|
448 | return this.$Prototype;
|
449 | }
|
450 |
|
451 |
|
452 | $SetPrototypeOf(V) {
|
453 |
|
454 | return _singletons.Properties.OrdinarySetPrototypeOf(this.$Realm, this, V);
|
455 | }
|
456 |
|
457 |
|
458 | $IsExtensible() {
|
459 |
|
460 | return (0, _index3.OrdinaryIsExtensible)(this.$Realm, this);
|
461 | }
|
462 |
|
463 |
|
464 | $PreventExtensions() {
|
465 |
|
466 | return (0, _index3.OrdinaryPreventExtensions)(this.$Realm, this);
|
467 | }
|
468 |
|
469 |
|
470 | $GetOwnProperty(P) {
|
471 |
|
472 | return _singletons.Properties.OrdinaryGetOwnProperty(this.$Realm, this, P);
|
473 | }
|
474 |
|
475 |
|
476 | $DefineOwnProperty(P, Desc) {
|
477 |
|
478 | return _singletons.Properties.OrdinaryDefineOwnProperty(this.$Realm, this, P, Desc);
|
479 | }
|
480 |
|
481 |
|
482 | $HasProperty(P) {
|
483 | if (this.unknownProperty !== undefined && this.$GetOwnProperty(P) === undefined) {
|
484 | _index2.AbstractValue.reportIntrospectionError(this, P);
|
485 |
|
486 | throw new _errors.FatalError();
|
487 | }
|
488 |
|
489 | return (0, _index3.OrdinaryHasProperty)(this.$Realm, this, P);
|
490 | }
|
491 |
|
492 |
|
493 | $Get(P, Receiver) {
|
494 | let prop = this.unknownProperty;
|
495 |
|
496 | if (prop !== undefined && prop.descriptor !== undefined && this.$GetOwnProperty(P) === undefined) {
|
497 | let desc = prop.descriptor;
|
498 | (0, _invariant.default)(desc !== undefined);
|
499 | let val = desc.value;
|
500 | (0, _invariant.default)(val instanceof _index2.AbstractValue);
|
501 | let propValue;
|
502 |
|
503 | if (P instanceof _index2.StringValue) {
|
504 | propValue = P;
|
505 | } else if (typeof P === "string") {
|
506 | propValue = new _index2.StringValue(this.$Realm, P);
|
507 | }
|
508 |
|
509 | if (val.kind === "widened numeric property") {
|
510 | (0, _invariant.default)(Receiver instanceof _index2.ArrayValue && _index2.ArrayValue.isIntrinsicAndHasWidenedNumericProperty(Receiver));
|
511 | let propName;
|
512 |
|
513 | if (P instanceof _index2.StringValue) {
|
514 | propName = P.value;
|
515 | } else {
|
516 | propName = P;
|
517 | }
|
518 |
|
519 | return (0, _index3.GetFromArrayWithWidenedNumericProperty)(this.$Realm, Receiver, propName);
|
520 | } else if (!propValue) {
|
521 | _index2.AbstractValue.reportIntrospectionError(val, "abstract computed property name");
|
522 |
|
523 | throw new _errors.FatalError();
|
524 | }
|
525 |
|
526 | return this.specializeJoin(val, propValue);
|
527 | }
|
528 |
|
529 |
|
530 | return (0, _index3.OrdinaryGet)(this.$Realm, this, P, Receiver);
|
531 | }
|
532 |
|
533 | _SafeGetDataPropertyValue(P) {
|
534 | let savedInvariantLevel = this.$Realm.invariantLevel;
|
535 |
|
536 | try {
|
537 | this.$Realm.invariantLevel = 0;
|
538 | let desc = this.$GetOwnProperty(P);
|
539 | return desc !== undefined && desc.value instanceof _index2.Value ? desc.value : this.$Realm.intrinsics.undefined;
|
540 | } finally {
|
541 | this.$Realm.invariantLevel = savedInvariantLevel;
|
542 | }
|
543 | }
|
544 |
|
545 | $GetPartial(P, Receiver) {
|
546 | if (Receiver instanceof _index2.AbstractValue && Receiver.getType() === _index2.StringValue && P === "length") {
|
547 | return _index2.AbstractValue.createFromTemplate(this.$Realm, lengthTemplate, _index2.NumberValue, [Receiver], lengthTemplateSrc);
|
548 | }
|
549 |
|
550 | if (!(P instanceof _index2.AbstractValue)) return this.$Get(P, Receiver);
|
551 |
|
552 |
|
553 |
|
554 | if (P.mightNotBeString() && P.mightNotBeNumber() && !P.isSimpleObject()) {
|
555 | if (this.$Realm.isInPureScope()) {
|
556 |
|
557 |
|
558 | _singletons.Havoc.value(this.$Realm, P);
|
559 | } else {
|
560 | let error = new _errors.CompilerDiagnostic("property key might not have a well behaved toString or be a symbol", this.$Realm.currentLocation, "PP0002", "RecoverableError");
|
561 |
|
562 | if (this.$Realm.handleError(error) !== "Recover") {
|
563 | throw new _errors.FatalError();
|
564 | }
|
565 | }
|
566 | }
|
567 |
|
568 |
|
569 | if (!this.isSimpleObject()) {
|
570 | if (this.$Realm.isInPureScope()) {
|
571 |
|
572 |
|
573 |
|
574 |
|
575 |
|
576 |
|
577 | _singletons.Havoc.value(this.$Realm, Receiver);
|
578 |
|
579 | return _index2.AbstractValue.createTemporalFromBuildFunction(this.$Realm, _index2.Value, [Receiver, P], (0, _generator.createOperationDescriptor)("OBJECT_GET_PARTIAL"), {
|
580 | skipInvariant: true,
|
581 | isPure: true
|
582 | });
|
583 | } else {
|
584 | let error = new _errors.CompilerDiagnostic("unknown property access might need to invoke a getter", this.$Realm.currentLocation, "PP0030", "RecoverableError");
|
585 |
|
586 | if (this.$Realm.handleError(error) !== "Recover") {
|
587 | throw new _errors.FatalError();
|
588 | }
|
589 | }
|
590 | }
|
591 |
|
592 | P = _singletons.To.ToStringAbstract(this.$Realm, P);
|
593 |
|
594 |
|
595 | let result;
|
596 |
|
597 | if (this.isPartialObject()) {
|
598 | if (isWidenedValue(P)) {
|
599 |
|
600 | return _index2.AbstractValue.createTemporalFromBuildFunction(this.$Realm, _index2.Value, [this, P], (0, _generator.createOperationDescriptor)("OBJECT_GET_PARTIAL"), {
|
601 | skipInvariant: true,
|
602 | isPure: true
|
603 | });
|
604 | }
|
605 |
|
606 | result = _index2.AbstractValue.createFromType(this.$Realm, _index2.Value, "sentinel member expression", [this, P]);
|
607 | } else {
|
608 | result = _index2.AbstractValue.createTemporalFromBuildFunction(this.$Realm, _index2.Value, [this, P], (0, _generator.createOperationDescriptor)("OBJECT_GET_PARTIAL"), {
|
609 | skipInvariant: true,
|
610 | isPure: true
|
611 | });
|
612 | }
|
613 |
|
614 |
|
615 |
|
616 | let prop = this.unknownProperty;
|
617 |
|
618 | if (prop !== undefined) {
|
619 | let desc = prop.descriptor;
|
620 |
|
621 | if (desc !== undefined) {
|
622 | let val = desc.value;
|
623 | (0, _invariant.default)(val instanceof _index2.AbstractValue);
|
624 |
|
625 | if (val.kind === "widened numeric property") {
|
626 | (0, _invariant.default)(Receiver instanceof _index2.ArrayValue && _index2.ArrayValue.isIntrinsicAndHasWidenedNumericProperty(Receiver));
|
627 | return (0, _index3.GetFromArrayWithWidenedNumericProperty)(this.$Realm, Receiver, P instanceof _index2.StringValue ? P.value : P);
|
628 | }
|
629 |
|
630 | result = this.specializeJoin(val, P);
|
631 | }
|
632 | }
|
633 |
|
634 |
|
635 |
|
636 | for (let [key, propertyBinding] of this.properties) {
|
637 | let desc = propertyBinding.descriptor;
|
638 | if (desc === undefined) continue;
|
639 |
|
640 | (0, _invariant.default)(desc.value !== undefined);
|
641 |
|
642 | let val = desc.value;
|
643 | (0, _invariant.default)(val instanceof _index2.Value);
|
644 |
|
645 | let cond = _index2.AbstractValue.createFromBinaryOp(this.$Realm, "===", P, new _index2.StringValue(this.$Realm, key), undefined, "check for known property");
|
646 |
|
647 | result = _index2.AbstractValue.createFromConditionalOp(this.$Realm, cond, val, result);
|
648 | }
|
649 |
|
650 | return result;
|
651 | }
|
652 |
|
653 | specializeJoin(absVal, propName) {
|
654 | if (absVal.kind === "widened property") {
|
655 | let ob = absVal.args[0];
|
656 |
|
657 | if (propName instanceof _index2.StringValue) {
|
658 | let pName = propName.value;
|
659 | let pNumber = +pName;
|
660 | if (pName === pNumber + "") propName = new _index2.NumberValue(this.$Realm, pNumber);
|
661 | }
|
662 |
|
663 | return _index2.AbstractValue.createTemporalFromBuildFunction(this.$Realm, absVal.getType(), [ob, propName], (0, _generator.createOperationDescriptor)("OBJECT_GET_PARTIAL"), {
|
664 | skipInvariant: true,
|
665 | isPure: true
|
666 | });
|
667 | }
|
668 |
|
669 | (0, _invariant.default)(absVal.args.length === 3 && absVal.kind === "conditional");
|
670 | let generic_cond = absVal.args[0];
|
671 | (0, _invariant.default)(generic_cond instanceof _index2.AbstractValue);
|
672 | let cond = this.specializeCond(generic_cond, propName);
|
673 | let arg1 = absVal.args[1];
|
674 | if (arg1 instanceof _index2.AbstractValue && arg1.args.length === 3) arg1 = this.specializeJoin(arg1, propName);
|
675 | let arg2 = absVal.args[2];
|
676 |
|
677 | if (arg2 instanceof _index2.AbstractValue) {
|
678 | if (arg2.kind === "template for prototype member expression") {
|
679 | let ob = arg2.args[0];
|
680 | arg2 = _index2.AbstractValue.createTemporalFromBuildFunction(this.$Realm, absVal.getType(), [ob, propName], (0, _generator.createOperationDescriptor)("OBJECT_GET_PARTIAL"), {
|
681 | skipInvariant: true,
|
682 | isPure: true
|
683 | });
|
684 | } else if (arg2.args.length === 3) {
|
685 | arg2 = this.specializeJoin(arg2, propName);
|
686 | }
|
687 | }
|
688 |
|
689 | return _index2.AbstractValue.createFromConditionalOp(this.$Realm, cond, arg1, arg2, absVal.expressionLocation);
|
690 | }
|
691 |
|
692 | specializeCond(absVal, propName) {
|
693 | if (absVal.kind === "template for property name condition") return _index2.AbstractValue.createFromBinaryOp(this.$Realm, "===", absVal.args[0], propName);
|
694 | return absVal;
|
695 | }
|
696 |
|
697 |
|
698 | $Set(P, V, Receiver) {
|
699 |
|
700 | return _singletons.Properties.OrdinarySet(this.$Realm, this, P, V, Receiver);
|
701 | }
|
702 |
|
703 | $SetPartial(P, V, Receiver) {
|
704 | if (!(P instanceof _index2.AbstractValue)) return this.$Set(P, V, Receiver);
|
705 | let pIsLoopVar = isWidenedValue(P);
|
706 |
|
707 | let pIsNumeric = _index2.Value.isTypeCompatibleWith(P.getType(), _index2.NumberValue);
|
708 |
|
709 |
|
710 |
|
711 |
|
712 | if (P.mightNotBeString() && P.mightNotBeNumber() && !P.isSimpleObject()) {
|
713 | if (this.$Realm.isInPureScope()) {
|
714 |
|
715 |
|
716 | _singletons.Havoc.value(this.$Realm, P);
|
717 | } else {
|
718 | let error = new _errors.CompilerDiagnostic("property key might not have a well behaved toString or be a symbol", this.$Realm.currentLocation, "PP0002", "RecoverableError");
|
719 |
|
720 | if (this.$Realm.handleError(error) !== "Recover") {
|
721 | throw new _errors.FatalError();
|
722 | }
|
723 | }
|
724 | }
|
725 |
|
726 |
|
727 |
|
728 | if (!this.isSimpleObject()) {
|
729 | if (this.$Realm.isInPureScope()) {
|
730 |
|
731 |
|
732 | _singletons.Havoc.value(this.$Realm, Receiver);
|
733 |
|
734 |
|
735 | _singletons.Havoc.value(this.$Realm, V);
|
736 |
|
737 | this.$Realm.evaluateWithPossibleThrowCompletion(() => {
|
738 | let generator = this.$Realm.generator;
|
739 | (0, _invariant.default)(generator);
|
740 | (0, _invariant.default)(P instanceof _index2.AbstractValue);
|
741 | generator.emitStatement([Receiver, P, V], (0, _generator.createOperationDescriptor)("OBJECT_SET_PARTIAL"));
|
742 | return this.$Realm.intrinsics.undefined;
|
743 | }, _index.TypesDomain.topVal, _index.ValuesDomain.topVal);
|
744 |
|
745 |
|
746 |
|
747 |
|
748 | return true;
|
749 | } else {
|
750 | let error = new _errors.CompilerDiagnostic("unknown property access might need to invoke a setter", this.$Realm.currentLocation, "PP0030", "RecoverableError");
|
751 |
|
752 | if (this.$Realm.handleError(error) !== "Recover") {
|
753 | throw new _errors.FatalError();
|
754 | }
|
755 | }
|
756 | }
|
757 |
|
758 |
|
759 |
|
760 |
|
761 |
|
762 | (0, _invariant.default)(this === Receiver || (0, _index3.HasCompatibleType)(Receiver, _index2.PrimitiveValue));
|
763 | P = _singletons.To.ToStringAbstract(this.$Realm, P);
|
764 |
|
765 | function createTemplate(realm, propName) {
|
766 | return _index2.AbstractValue.createFromBinaryOp(realm, "===", propName, new _index2.StringValue(realm, ""), undefined, "template for property name condition");
|
767 | }
|
768 |
|
769 | let prop;
|
770 |
|
771 | if (this.unknownProperty === undefined) {
|
772 | prop = {
|
773 | descriptor: undefined,
|
774 | object: this,
|
775 | key: P
|
776 | };
|
777 | this.unknownProperty = prop;
|
778 | } else {
|
779 | prop = this.unknownProperty;
|
780 | }
|
781 |
|
782 | this.$Realm.recordModifiedProperty(prop);
|
783 | let desc = prop.descriptor;
|
784 |
|
785 | if (desc === undefined) {
|
786 | let newVal = V;
|
787 |
|
788 | if (!(V instanceof _index2.UndefinedValue) && !isWidenedValue(P)) {
|
789 |
|
790 | let cond = createTemplate(this.$Realm, P);
|
791 |
|
792 | let sentinel = _index2.AbstractValue.createFromType(this.$Realm, _index2.Value, "template for prototype member expression", [Receiver, P]);
|
793 |
|
794 | newVal = _index2.AbstractValue.createFromConditionalOp(this.$Realm, cond, V, sentinel);
|
795 | }
|
796 |
|
797 | prop.descriptor = {
|
798 | writable: true,
|
799 | enumerable: true,
|
800 | configurable: true,
|
801 | value: newVal
|
802 | };
|
803 | } else {
|
804 |
|
805 | let oldVal = desc.value;
|
806 | (0, _invariant.default)(oldVal instanceof _index2.Value);
|
807 | let newVal = oldVal;
|
808 |
|
809 | if (!(V instanceof _index2.UndefinedValue)) {
|
810 | if (isWidenedValue(P)) {
|
811 | newVal = V;
|
812 | } else {
|
813 | let cond = createTemplate(this.$Realm, P);
|
814 | newVal = _index2.AbstractValue.createFromConditionalOp(this.$Realm, cond, V, oldVal);
|
815 | }
|
816 | }
|
817 |
|
818 | desc.value = newVal;
|
819 | }
|
820 |
|
821 |
|
822 |
|
823 |
|
824 | let savedUnknownProperty = this.unknownProperty;
|
825 | this.unknownProperty = undefined;
|
826 |
|
827 | for (let [key, propertyBinding] of this.properties) {
|
828 | if (pIsLoopVar && pIsNumeric) {
|
829 |
|
830 | if (key !== +key + "") continue;
|
831 | this.properties.delete(key);
|
832 | continue;
|
833 | }
|
834 |
|
835 | let oldVal = this.$Realm.intrinsics.empty;
|
836 |
|
837 | if (propertyBinding.descriptor && propertyBinding.descriptor.value) {
|
838 | oldVal = propertyBinding.descriptor.value;
|
839 | (0, _invariant.default)(oldVal instanceof _index2.Value);
|
840 | }
|
841 |
|
842 | let cond = _index2.AbstractValue.createFromBinaryOp(this.$Realm, "===", P, new _index2.StringValue(this.$Realm, key));
|
843 |
|
844 | let newVal = _index2.AbstractValue.createFromConditionalOp(this.$Realm, cond, V, oldVal);
|
845 |
|
846 | _singletons.Properties.OrdinarySet(this.$Realm, this, key, newVal, Receiver);
|
847 | }
|
848 |
|
849 | this.unknownProperty = savedUnknownProperty;
|
850 | return true;
|
851 | }
|
852 |
|
853 |
|
854 | $Delete(P) {
|
855 | if (this.unknownProperty !== undefined) {
|
856 |
|
857 | _index2.AbstractValue.reportIntrospectionError(this, P);
|
858 |
|
859 | throw new _errors.FatalError();
|
860 | }
|
861 |
|
862 |
|
863 | return _singletons.Properties.OrdinaryDelete(this.$Realm, this, P);
|
864 | }
|
865 |
|
866 |
|
867 | $OwnPropertyKeys() {
|
868 | return (0, _index3.OrdinaryOwnPropertyKeys)(this.$Realm, this);
|
869 | }
|
870 |
|
871 | static refuseSerializationOnPropertyBinding(pb) {
|
872 | if (pb.object.refuseSerialization) return true;
|
873 | if (pb.internalSlot && typeof pb.key === "string" && pb.key[0] === "_") return true;
|
874 | return false;
|
875 | }
|
876 |
|
877 | }
|
878 |
|
879 | exports.default = ObjectValue;
|
880 |
|
881 | _defineProperty(ObjectValue, "trackedPropertyNames", ["_isPartial", "_isHavoced", "_isSimple", "_isFinal", "_simplicityIsTransitive", "_temporalAlias", "$ArrayIteratorNextIndex", "$DateValue", "$Extensible", "$IteratedList", "$IteratedObject", "$IteratedSet", "$IteratedString", "$Map", "$MapData", "$MapNextIndex", "$Prototype", "$SetData", "$SetNextIndex", "$StringIteratorNextIndex", "$WeakMapData", "$WeakSetData"]);
|
882 |
|
883 | _defineProperty(ObjectValue, "trackedPropertyBindingNames", new Map());
|
884 |
|
\ | No newline at end of file |