Skip to content

Commit

Permalink
[NTI] Groundwork to enable CheckAccessControls to run with NTI.
Browse files Browse the repository at this point in the history
This is just the NTI-only changes extracted from cl/128232390.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=128381081
  • Loading branch information
aravind-pg authored and blickly committed Jul 25, 2016
1 parent fd1edcb commit 4f4ec6f
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 52 deletions.
10 changes: 7 additions & 3 deletions src/com/google/javascript/jscomp/GlobalTypeInfo.java
Expand Up @@ -46,6 +46,7 @@
import com.google.javascript.rhino.TypeI;
import com.google.javascript.rhino.TypeIRegistry;
import com.google.javascript.rhino.jstype.JSTypeNative;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -2491,9 +2492,12 @@ public JSType getNativeType(JSTypeNative typeId) {

@Override
public String getReadableTypeName(Node n) {
// TODO(aravindpg): Unimplemented for now. Implementation should follow the one in
// JSTypeRegistry.
throw new UnsupportedOperationException("getReadableTypeName not implemented yet");
// TODO(aravindpg): stub, could implement in a more sophisticated way, following the
// implementation in JSTypeRegistry.
if (n.getTypeI() == null) {
return "<node (" + compiler.toSource(n) + ")>";
}
return n.getTypeI().toString();
}

@Override
Expand Down
10 changes: 8 additions & 2 deletions src/com/google/javascript/jscomp/NTIScope.java
Expand Up @@ -355,6 +355,9 @@ public JSType getDeclaredTypeOf(String name) {
}
NTIScope funScope = (NTIScope) decl.getFunctionScope();
if (funScope != null) {
Preconditions.checkNotNull(
funScope.getDeclaredFunctionType(),
"decl=%s, funScope=%s", decl, funScope);
return getCommonTypes().fromFunctionType(
funScope.getDeclaredFunctionType().toFunctionType());
}
Expand Down Expand Up @@ -632,8 +635,11 @@ public Declaration getDeclaration(String name, boolean includeTypes) {
public JSType getType(String typeName) {
Preconditions.checkNotNull(
preservedNamespaces, "Failed to preserve namespaces post-finalization");
RawNominalType nominalType = (RawNominalType) preservedNamespaces.get(typeName);
return nominalType == null ? null : nominalType.getInstanceAsJSType();
Namespace ns = preservedNamespaces.get(typeName);
if (ns instanceof RawNominalType) {
return ((RawNominalType) ns).getInstanceAsJSType();
}
return null;
}

void resolveTypedefs(JSTypeCreatorFromJSDoc typeParser) {
Expand Down
20 changes: 7 additions & 13 deletions src/com/google/javascript/jscomp/NewTypeInference.java
Expand Up @@ -39,6 +39,7 @@
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TypeI;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -1684,7 +1685,7 @@ private EnvTypePair analyzeAssignFwd(
Node expr, TypeEnv inEnv, JSType requiredType, JSType specializedType) {
if (expr.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
expr.removeProp(Node.ANALYZED_DURING_GTI);
// No need to set a type on the assignment expression
markAndGetTypeOfPreanalyzedNode(expr.getFirstChild(), inEnv, true);
return new EnvTypePair(inEnv, requiredType);
}
mayWarnAboutConst(expr);
Expand Down Expand Up @@ -3742,6 +3743,9 @@ private static class LValueResultFwd {
// Some expressions are analyzed during GTI, so they're skipped here.
// But we must annotate them with a type anyway.
private JSType markAndGetTypeOfPreanalyzedNode(Node qnameNode, TypeEnv env, boolean isFwd) {
if (NodeUtil.getRootOfQualifiedName(qnameNode).isThis()) {
return null;
}
switch (qnameNode.getType()) {
case NAME: {
JSType result = envGetType(env, qnameNode.getString());
Expand All @@ -3759,17 +3763,6 @@ private JSType markAndGetTypeOfPreanalyzedNode(Node qnameNode, TypeEnv env, bool
result = recvType.getProp(new QualifiedName(pname));
}

// TODO(dimvar): revisit this decision?
// The old type system has a special type for Foo.prototype, even though
// it is Object with extra properties.
// We don't have a special type, so, for simplicity when converting to
// the old types, we cheat here and annotate the Foo.prototype node as
// a Foo instance.
if (pname.equals("prototype")
&& (recvType.isConstructor() || recvType.isInterfaceDefinition())) {
FunctionType ft = recvType.getFunTypeIfSingletonObj();
result = ft.getInstanceTypeOfCtor();
}
if (result == null) {
warnings.add(JSError.make(qnameNode, UNKNOWN_NAMESPACE_PROPERTY,
qnameNode.getQualifiedName()));
Expand All @@ -3784,7 +3777,8 @@ private JSType markAndGetTypeOfPreanalyzedNode(Node qnameNode, TypeEnv env, bool
}
default:
throw new RuntimeException(
"markAndGetTypeOfPreanalyzedNode: unexpected node " + qnameNode.getType());
"markAndGetTypeOfPreanalyzedNode: unexpected node " + compiler.toSource(qnameNode)
+ " with token " + qnameNode.getType());
}
}

Expand Down
Expand Up @@ -216,7 +216,7 @@ public JSType getSuperPrototype() {
Preconditions.checkState(isUniqueConstructor());
NominalType nt = getNominalTypeIfSingletonObj(this.nominalType);
NominalType superClass = nt.getInstantiatedSuperclass();
return superClass == null ? null : superClass.getPrototype();
return superClass == null ? null : superClass.getPrototypePropertyOfCtor();
}

public boolean isQmarkFunction() {
Expand Down
64 changes: 49 additions & 15 deletions src/com/google/javascript/jscomp/newtypes/JSType.java
Expand Up @@ -22,12 +22,14 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.javascript.jscomp.NodeUtil;
import com.google.javascript.jscomp.parsing.parser.util.format.SimpleFormat;
import com.google.javascript.rhino.FunctionTypeI;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.ObjectTypeI;
import com.google.javascript.rhino.TypeI;

import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
Expand Down Expand Up @@ -1532,7 +1534,7 @@ public boolean isUnknownType() {

@Override
public TypeI restrictByNotNullOrUndefined() {
throw new UnsupportedOperationException("restrictByNotNullOrUndefined not implemented yet.");
return this.removeType(NULL_OR_UNDEF);
}

@Override
Expand All @@ -1546,8 +1548,8 @@ public ObjectTypeI toMaybeObjectType() {
}

@Override
public JSType autoboxAndGetObject() {
throw new UnsupportedOperationException("autoboxAndGetObject not implemented yet");
public ObjectTypeI autoboxAndGetObject() {
return this.autobox().restrictByNotNullOrUndefined().toMaybeObjectType();
}

@Override
Expand All @@ -1572,7 +1574,8 @@ public int hashCode() {

@Override
public String getDisplayName() {
throw new UnsupportedOperationException("getDisplayName not implemented yet");
// TODO(aravindpg): stub, could implement in a more sophisticated way
return toString();
}

@Override
Expand All @@ -1594,7 +1597,13 @@ public String getReferenceName() {

@Override
public Node getSource() {
throw new UnsupportedOperationException("getSource not implemented yet");
if (isConstructor()) {
JSType instance = getFunTypeIfSingletonObj().getInstanceTypeOfCtor();
return instance.getNominalTypeIfSingletonObj().getDefSite();
}
return this.isSingletonObj()
? getNominalTypeIfSingletonObj().getDefSite()
: null;
}

@Override
Expand Down Expand Up @@ -1626,32 +1635,52 @@ public TypeI getReturnType() {

@Override
public FunctionTypeI getConstructor() {
throw new UnsupportedOperationException("getConstructor not implemented yet");
Preconditions.checkState(this.isSingletonObj());
FunctionType ctorType = this.getNominalTypeIfSingletonObj().getConstructorFunction();
return commonTypes.fromFunctionType(ctorType);
}

@Override
public JSType getPrototypeObject() {
throw new UnsupportedOperationException("getPrototypeObject not implemented yet");
Preconditions.checkState(this.isSingletonObj());
if (this.equals(TOP_OBJECT)) {
// In NTI, TOP_OBJECT is the supertype of all objects, which is
// the same as an instance of Object. In JS's dynamic semantics, the
// only object without a __proto__ is Object.prototype, but it's not
// representable in NTI.
// Returning null for TOP_OBJECT is technically wrong, because an instance
// of Object has a __proto__, but it doesn't break any tests and we need it
// to avoid going up the prototype chain forever.
return null;
} else {
return getNominalTypeIfSingletonObj().getPrototypePropertyOfCtor();
}
}

@Override
public JSDocInfo getJSDocInfo() {
throw new UnsupportedOperationException("getJSDocInfo not implemented yet");
return getSource() == null ? null : NodeUtil.getBestJSDocInfo(getSource());
}

@Override
public JSDocInfo getOwnPropertyJSDocInfo(String propertyName) {
throw new UnsupportedOperationException("getOwnPropertyJSDocInfo not implemented yet");
Node defsite = this.getOwnPropertyDefsite(propertyName);
if (defsite != null) {
return NodeUtil.getBestJSDocInfo(defsite);
}
return null;
}

@Override
public Node getOwnPropertyDefsite(String propertyName) {
throw new UnsupportedOperationException("getOwnPropertyDefsite not implemented yet");
Preconditions.checkState(this.isSingletonObj());
return this.getObjTypeIfSingletonObj().getOwnPropertyDefSite(propertyName);
}

@Override
public Node getPropertyDefsite(String propertyName) {
throw new UnsupportedOperationException("getPropertyDefsite not implemented yet");
Preconditions.checkState(this.isSingletonObj());
return this.getObjTypeIfSingletonObj().getPropertyDefSite(propertyName);
}

@Override
Expand All @@ -1661,22 +1690,27 @@ public JSType getLowestSupertypeWithProperty(String propertyName, boolean isOver

@Override
public boolean isPrototypeObject() {
throw new UnsupportedOperationException("isPrototypeObject not implemented yet");
// TODO(aravindpg): this is just a complete stub to ensure that we never enter a codepath
// that depends on us being a prototype object.
return false;
}

@Override
public boolean isInstanceofObject() {
throw new UnsupportedOperationException("isObjectLiteral not implemented yet");
return this.isSingletonObj() && this.getNominalTypeIfSingletonObj().isBuiltinObject();
}

@Override
public boolean isInstanceType() {
throw new UnsupportedOperationException("isInstanceType not implemented yet");
Preconditions.checkState(this.isSingletonObj());
return this.getNominalTypeIfSingletonObj().isClass();
}

@Override
public boolean hasProperty(String propertyName) {
throw new UnsupportedOperationException("hasProperty not implemented yet");
Preconditions.checkState(this.isSingletonObj());
Preconditions.checkArgument(!propertyName.contains("."));
return hasProp(new QualifiedName(propertyName));
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/com/google/javascript/jscomp/newtypes/Namespace.java
Expand Up @@ -199,6 +199,8 @@ final Property getNsProp(String pname) {
if (this.namespaces.containsKey(pname)) {
Namespace subns = this.namespaces.get(pname);
Preconditions.checkState(subns.namespaceType != null);
// TODO(aravindpg): we need a defsite here for the test
// CheckAccessControlsTest::testFileoverviewVisibilityDoesNotApplyToGoogProvidedNamespace4
return Property.make(subns.namespaceType, subns.namespaceType);
}
if (this.otherProps.containsKey(pname)) {
Expand Down
24 changes: 22 additions & 2 deletions src/com/google/javascript/jscomp/newtypes/NominalType.java
Expand Up @@ -22,6 +22,8 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.javascript.rhino.Node;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -49,8 +51,11 @@ public final class NominalType {
this.rawType = rawType;
}

// This should only be called during GlobalTypeInfo.
// This should only be called during GlobalTypeInfo. All other calling contexts
// expect fully-instantiated types for properties defined on types, etc., but by accessing
// the raw nominal type directly they will get the uninstantiated generic types instead.
public RawNominalType getRawNominalType() {
// If the raw nominal type is finalized, then we are not in GlobalTypeInfo any more.
Preconditions.checkState(!this.rawType.isFinalized());
return this.rawType;
}
Expand Down Expand Up @@ -142,6 +147,14 @@ public boolean isUninstantiatedGenericType() {
return this.rawType.isGeneric() && typeMap.isEmpty();
}

public Node getDefSite() {
return this.rawType.getDefSite();
}

public FunctionType getConstructorFunction() {
return this.rawType.getConstructorFunction();
}

NominalType instantiateGenerics(List<JSType> types) {
ImmutableList<String> typeParams = this.rawType.getTypeParameters();
Preconditions.checkState(types.size() == typeParams.size());
Expand Down Expand Up @@ -237,7 +250,7 @@ public NominalType getInstantiatedSuperclass() {
return this.rawType.getSuperClass().instantiateGenerics(typeMap);
}

public JSType getPrototype() {
public JSType getPrototypePropertyOfCtor() {
Preconditions.checkState(this.rawType.isFinalized());
return this.rawType.getCtorPropDeclaredType("prototype")
.substituteGenerics(typeMap);
Expand Down Expand Up @@ -277,6 +290,8 @@ Property getProp(String pname) {
return Property.make(elmType, null);
}
Property p = this.rawType.getProp(pname);
// TODO(aravindpg): Also look for getters and setters specially (in RawNominalType::protoProps),
// but avoid putting them in the hot path of getProp.
return p == null ? null : p.substituteGenerics(typeMap);
}

Expand All @@ -288,6 +303,11 @@ public JSType getPropDeclaredType(String pname) {
return type.substituteGenerics(typeMap);
}

Property getOwnProp(String pname) {
Property p = this.rawType.getOwnProp(pname);
return p == null ? null : p.substituteGenerics(typeMap);
}

public boolean hasConstantProp(String pname) {
Property p = this.rawType.getProp(pname);
return p != null && p.isConstant();
Expand Down

0 comments on commit 4f4ec6f

Please sign in to comment.