This repository has been archived by the owner on Feb 12, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 421
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Re-land typed descriptors and printer (#2511)
Summary: Release notes: landing two previously reverted PRs I found the issue. Flow doesn't support optional fields in classes. This effectively becomes enforced with Babel 7 since it treats the type annotations as field initializers. Which means that these fields always gets created. We happened to only use this newer plugin for class fields internally which broke our builds only there. 2b4546d Use `undefined` instead of missing to represent absent field in descriptors. Fixed all the callsites that checks for `hasOwnProperty` or `in` that I could find. 922d40c Fixes a Flow issue in the text printer. I filed a [follow up issue for ObjectValue](#2510) since it has the same problem. Pull Request resolved: #2511 Reviewed By: trueadm Differential Revision: D9569949 Pulled By: sebmarkbage fbshipit-source-id: f8bf84c4385de4f0ff6bcd45badacd3b8c88c533
- Loading branch information
1 parent
69699c2
commit 54be9b5
Showing
77 changed files
with
3,130 additions
and
1,494 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
*/ | ||
|
||
/* @flow */ | ||
|
||
import invariant from "./invariant.js"; | ||
import type { AbstractValue, UndefinedValue, Value } from "./values/index.js"; | ||
import { CompilerDiagnostic, FatalError } from "./errors.js"; | ||
import type { CallableObjectValue } from "./types.js"; | ||
import type { Realm } from "./realm.js"; | ||
|
||
export class Descriptor { | ||
constructor() { | ||
invariant(this.constructor !== Descriptor, "Descriptor is an abstract base class"); | ||
} | ||
throwIfNotConcrete(realm: Realm): PropertyDescriptor { | ||
let error = new CompilerDiagnostic( | ||
"only known descriptors supported", | ||
realm.currentLocation, | ||
"PP0042", | ||
"FatalError" | ||
); | ||
realm.handleError(error); | ||
throw new FatalError(); | ||
} | ||
mightHaveBeenDeleted(): boolean { | ||
invariant(false, "should have been overridden by subclass"); | ||
} | ||
} | ||
|
||
export type DescriptorInitializer = {| | ||
writable?: boolean, | ||
enumerable?: boolean, | ||
configurable?: boolean, | ||
|
||
value?: Value, | ||
|
||
get?: UndefinedValue | CallableObjectValue | AbstractValue, | ||
set?: UndefinedValue | CallableObjectValue | AbstractValue, | ||
|}; | ||
|
||
// Normal descriptors are returned just like spec descriptors | ||
export class PropertyDescriptor extends Descriptor { | ||
writable: void | boolean; | ||
enumerable: void | boolean; | ||
configurable: void | boolean; | ||
|
||
// If value instanceof EmptyValue, then this descriptor indicates that the | ||
// corresponding property has been deleted. | ||
value: void | Value; | ||
|
||
get: void | UndefinedValue | CallableObjectValue | AbstractValue; | ||
set: void | UndefinedValue | CallableObjectValue | AbstractValue; | ||
|
||
constructor(desc: DescriptorInitializer | PropertyDescriptor) { | ||
super(); | ||
this.writable = desc.writable; | ||
this.enumerable = desc.enumerable; | ||
this.configurable = desc.configurable; | ||
this.value = desc.value; | ||
this.get = desc.get; | ||
this.set = desc.set; | ||
} | ||
|
||
throwIfNotConcrete(realm: Realm): PropertyDescriptor { | ||
return this; | ||
} | ||
mightHaveBeenDeleted(): boolean { | ||
if (this.value === undefined) return false; | ||
return this.value.mightHaveBeenDeleted(); | ||
} | ||
} | ||
|
||
// Only internal properties (those starting with $ / where internalSlot of owning property binding is true) will ever have array values. | ||
export class InternalSlotDescriptor extends Descriptor { | ||
value: void | Value | Array<any>; | ||
|
||
constructor(value?: void | Value | Array<any>) { | ||
super(); | ||
this.value = Array.isArray(value) ? value.slice(0) : value; | ||
} | ||
|
||
mightHaveBeenDeleted(): boolean { | ||
return false; | ||
} | ||
} | ||
|
||
// Only used if the result of a join of two descriptors is not a data descriptor with identical attribute values. | ||
// When present, any update to the property must produce effects that are the join of updating both descriptors, | ||
// using joinCondition as the condition of the join. | ||
export class AbstractJoinedDescriptor extends Descriptor { | ||
joinCondition: AbstractValue; | ||
// An undefined descriptor means it might be empty in this branch. | ||
descriptor1: void | Descriptor; | ||
descriptor2: void | Descriptor; | ||
|
||
constructor(joinCondition: AbstractValue, descriptor1?: Descriptor, descriptor2?: Descriptor) { | ||
super(); | ||
this.joinCondition = joinCondition; | ||
this.descriptor1 = descriptor1; | ||
this.descriptor2 = descriptor2; | ||
} | ||
mightHaveBeenDeleted(): boolean { | ||
if (!this.descriptor1 || this.descriptor1.mightHaveBeenDeleted()) { | ||
return true; | ||
} | ||
if (!this.descriptor2 || this.descriptor2.mightHaveBeenDeleted()) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
} | ||
|
||
export function cloneDescriptor(d: void | PropertyDescriptor): void | PropertyDescriptor { | ||
if (d === undefined) return undefined; | ||
return new PropertyDescriptor(d); | ||
} | ||
|
||
// does not check if the contents of value properties are the same | ||
export function equalDescriptors(d1: PropertyDescriptor, d2: PropertyDescriptor): boolean { | ||
if (d1.writable !== d2.writable) return false; | ||
if (d1.enumerable !== d2.enumerable) return false; | ||
if (d1.configurable !== d2.configurable) return false; | ||
if (d1.value !== undefined) { | ||
if (d2.value === undefined) return false; | ||
} | ||
if (d1.get !== d2.get) return false; | ||
if (d1.set !== d2.set) return false; | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.