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.TypeI;
import com.google.javascript.rhino.TypeIRegistry; import com.google.javascript.rhino.TypeIRegistry;
import com.google.javascript.rhino.jstype.JSTypeNative; import com.google.javascript.rhino.jstype.JSTypeNative;

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


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


@Override @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(); NTIScope funScope = (NTIScope) decl.getFunctionScope();
if (funScope != null) { if (funScope != null) {
Preconditions.checkNotNull(
funScope.getDeclaredFunctionType(),
"decl=%s, funScope=%s", decl, funScope);
return getCommonTypes().fromFunctionType( return getCommonTypes().fromFunctionType(
funScope.getDeclaredFunctionType().toFunctionType()); funScope.getDeclaredFunctionType().toFunctionType());
} }
Expand Down Expand Up @@ -632,8 +635,11 @@ public Declaration getDeclaration(String name, boolean includeTypes) {
public JSType getType(String typeName) { public JSType getType(String typeName) {
Preconditions.checkNotNull( Preconditions.checkNotNull(
preservedNamespaces, "Failed to preserve namespaces post-finalization"); preservedNamespaces, "Failed to preserve namespaces post-finalization");
RawNominalType nominalType = (RawNominalType) preservedNamespaces.get(typeName); Namespace ns = preservedNamespaces.get(typeName);
return nominalType == null ? null : nominalType.getInstanceAsJSType(); if (ns instanceof RawNominalType) {
return ((RawNominalType) ns).getInstanceAsJSType();
}
return null;
} }


void resolveTypedefs(JSTypeCreatorFromJSDoc typeParser) { 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.Node;
import com.google.javascript.rhino.Token; import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.TypeI; import com.google.javascript.rhino.TypeI;

import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
Expand Down Expand Up @@ -1684,7 +1685,7 @@ private EnvTypePair analyzeAssignFwd(
Node expr, TypeEnv inEnv, JSType requiredType, JSType specializedType) { Node expr, TypeEnv inEnv, JSType requiredType, JSType specializedType) {
if (expr.getBooleanProp(Node.ANALYZED_DURING_GTI)) { if (expr.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
expr.removeProp(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); return new EnvTypePair(inEnv, requiredType);
} }
mayWarnAboutConst(expr); 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. // Some expressions are analyzed during GTI, so they're skipped here.
// But we must annotate them with a type anyway. // But we must annotate them with a type anyway.
private JSType markAndGetTypeOfPreanalyzedNode(Node qnameNode, TypeEnv env, boolean isFwd) { private JSType markAndGetTypeOfPreanalyzedNode(Node qnameNode, TypeEnv env, boolean isFwd) {
if (NodeUtil.getRootOfQualifiedName(qnameNode).isThis()) {
return null;
}
switch (qnameNode.getType()) { switch (qnameNode.getType()) {
case NAME: { case NAME: {
JSType result = envGetType(env, qnameNode.getString()); 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)); 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) { if (result == null) {
warnings.add(JSError.make(qnameNode, UNKNOWN_NAMESPACE_PROPERTY, warnings.add(JSError.make(qnameNode, UNKNOWN_NAMESPACE_PROPERTY,
qnameNode.getQualifiedName())); qnameNode.getQualifiedName()));
Expand All @@ -3784,7 +3777,8 @@ private JSType markAndGetTypeOfPreanalyzedNode(Node qnameNode, TypeEnv env, bool
} }
default: default:
throw new RuntimeException( 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()); Preconditions.checkState(isUniqueConstructor());
NominalType nt = getNominalTypeIfSingletonObj(this.nominalType); NominalType nt = getNominalTypeIfSingletonObj(this.nominalType);
NominalType superClass = nt.getInstantiatedSuperclass(); NominalType superClass = nt.getInstantiatedSuperclass();
return superClass == null ? null : superClass.getPrototype(); return superClass == null ? null : superClass.getPrototypePropertyOfCtor();
} }


public boolean isQmarkFunction() { 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.Iterables;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Sets; 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.jscomp.parsing.parser.util.format.SimpleFormat;
import com.google.javascript.rhino.FunctionTypeI; import com.google.javascript.rhino.FunctionTypeI;
import com.google.javascript.rhino.JSDocInfo; import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.Node; import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.ObjectTypeI; import com.google.javascript.rhino.ObjectTypeI;
import com.google.javascript.rhino.TypeI; import com.google.javascript.rhino.TypeI;

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


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


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


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


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


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


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


@Override @Override
public Node getSource() { 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 @Override
Expand Down Expand Up @@ -1626,32 +1635,52 @@ public TypeI getReturnType() {


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


@Override @Override
public JSType getPrototypeObject() { 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 @Override
public JSDocInfo getJSDocInfo() { public JSDocInfo getJSDocInfo() {
throw new UnsupportedOperationException("getJSDocInfo not implemented yet"); return getSource() == null ? null : NodeUtil.getBestJSDocInfo(getSource());
} }


@Override @Override
public JSDocInfo getOwnPropertyJSDocInfo(String propertyName) { 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 @Override
public Node getOwnPropertyDefsite(String propertyName) { public Node getOwnPropertyDefsite(String propertyName) {
throw new UnsupportedOperationException("getOwnPropertyDefsite not implemented yet"); Preconditions.checkState(this.isSingletonObj());
return this.getObjTypeIfSingletonObj().getOwnPropertyDefSite(propertyName);
} }


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


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


@Override @Override
public boolean isPrototypeObject() { 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 @Override
public boolean isInstanceofObject() { public boolean isInstanceofObject() {
throw new UnsupportedOperationException("isObjectLiteral not implemented yet"); return this.isSingletonObj() && this.getNominalTypeIfSingletonObj().isBuiltinObject();
} }


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


@Override @Override
public boolean hasProperty(String propertyName) { 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)) { if (this.namespaces.containsKey(pname)) {
Namespace subns = this.namespaces.get(pname); Namespace subns = this.namespaces.get(pname);
Preconditions.checkState(subns.namespaceType != null); Preconditions.checkState(subns.namespaceType != null);
// TODO(aravindpg): we need a defsite here for the test
// CheckAccessControlsTest::testFileoverviewVisibilityDoesNotApplyToGoogProvidedNamespace4
return Property.make(subns.namespaceType, subns.namespaceType); return Property.make(subns.namespaceType, subns.namespaceType);
} }
if (this.otherProps.containsKey(pname)) { 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.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.javascript.rhino.Node;

import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
Expand Down Expand Up @@ -49,8 +51,11 @@ public final class NominalType {
this.rawType = rawType; 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() { public RawNominalType getRawNominalType() {
// If the raw nominal type is finalized, then we are not in GlobalTypeInfo any more.
Preconditions.checkState(!this.rawType.isFinalized()); Preconditions.checkState(!this.rawType.isFinalized());
return this.rawType; return this.rawType;
} }
Expand Down Expand Up @@ -142,6 +147,14 @@ public boolean isUninstantiatedGenericType() {
return this.rawType.isGeneric() && typeMap.isEmpty(); 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) { NominalType instantiateGenerics(List<JSType> types) {
ImmutableList<String> typeParams = this.rawType.getTypeParameters(); ImmutableList<String> typeParams = this.rawType.getTypeParameters();
Preconditions.checkState(types.size() == typeParams.size()); Preconditions.checkState(types.size() == typeParams.size());
Expand Down Expand Up @@ -237,7 +250,7 @@ public NominalType getInstantiatedSuperclass() {
return this.rawType.getSuperClass().instantiateGenerics(typeMap); return this.rawType.getSuperClass().instantiateGenerics(typeMap);
} }


public JSType getPrototype() { public JSType getPrototypePropertyOfCtor() {
Preconditions.checkState(this.rawType.isFinalized()); Preconditions.checkState(this.rawType.isFinalized());
return this.rawType.getCtorPropDeclaredType("prototype") return this.rawType.getCtorPropDeclaredType("prototype")
.substituteGenerics(typeMap); .substituteGenerics(typeMap);
Expand Down Expand Up @@ -277,6 +290,8 @@ Property getProp(String pname) {
return Property.make(elmType, null); return Property.make(elmType, null);
} }
Property p = this.rawType.getProp(pname); 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); return p == null ? null : p.substituteGenerics(typeMap);
} }


Expand All @@ -288,6 +303,11 @@ public JSType getPropDeclaredType(String pname) {
return type.substituteGenerics(typeMap); 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) { public boolean hasConstantProp(String pname) {
Property p = this.rawType.getProp(pname); Property p = this.rawType.getProp(pname);
return p != null && p.isConstant(); return p != null && p.isConstant();
Expand Down

0 comments on commit 4f4ec6f

Please sign in to comment.