Example #1
0
        public override JSVariableField CreateInnerField(JSVariableField outerField)
        {
            return(outerField.IfNotNull(o =>
            {
                // blindly create an inner reference field for with scopes, no matter what it
                // is. globals and predefined values can be hijacked by object properties in
                // this scope.
                var withField = AddField(CreateField(outerField));

                // and we need to make sure that any field that may be referenced from inside
                // a with-statement does not get automatically renamed
                outerField.CanCrunch = false;

                // if the outer field is an undefined global, then we want to flag it with a
                // special attribute that tells us that it might not actually be an undefined global,
                // because it might just be a property reference on the with-object.
                if (outerField.FieldType == FieldType.UndefinedGlobal)
                {
                    do
                    {
                        outerField.Attributes |= FieldAttributes.RTSpecialName;
                    } while ((outerField = outerField.OuterField) != null);
                }

                return withField;
            }));
        }
Example #2
0
        void DefineParameters()
        {
            var functionObject = (FunctionObject)Owner;

            if (functionObject.ParameterDeclarations != null)
            {
                // for each parameter...
                foreach (ParameterDeclaration parameter in functionObject.ParameterDeclarations)
                {
                    foreach (var nameDeclaration in BindingsVisitor.Bindings(parameter.Binding))
                    {
                        // see if it's already defined
                        var argumentField = this[nameDeclaration.Name];
                        if (argumentField == null)
                        {
                            // not already defined -- create a field now
                            argumentField = new JSVariableField(FieldType.Argument, nameDeclaration.Name, 0, null)
                            {
                                Position        = parameter.Position,
                                OriginalContext = parameter.Context,
                                CanCrunch       = !nameDeclaration.RenameNotAllowed
                            };

                            this.AddField(argumentField);
                        }

                        // make the parameter reference the field and the field reference
                        // the parameter as its declaration
                        nameDeclaration.VariableField = argumentField;
                        argumentField.Declarations.Add(nameDeclaration);
                    }
                }
            }
        }
Example #3
0
        JSVariableField ResolveFromCollection(string name, HashSet <string> collection, FieldType fieldType, bool isFunction)
        {
            if (collection.Contains(name))
            {
                var variableField = new JSVariableField(fieldType, name, 0, null);
                variableField.IsFunction = isFunction;
                return(AddField(variableField));
            }

            return(null);
        }
Example #4
0
        public override JSVariableField CreateInnerField(JSVariableField outerField)
        {
            return(outerField.IfNotNull(o =>
            {
                // blindly create an inner reference field for with scopes, no matter what it
                // is. globals and predefined values can be hijacked by object properties in
                // this scope.
                var withField = AddField(CreateField(outerField));

                return withField;
            }));
        }
Example #5
0
        public override JSVariableField this[string name]
        {
            get
            {
                // check the name table
                JSVariableField variableField = base[name];

                // not found so far, check the global properties
                if (variableField == null)
                {
                    variableField = ResolveFromCollection(name, m_globalProperties, FieldType.Predefined, false);
                }

                // not found so far, check the global properties
                if (variableField == null)
                {
                    variableField = ResolveFromCollection(name, m_globalFunctions, FieldType.Predefined, true);
                }

                // if not found so far, check to see if this value is provided in our "assumed"
                // global list specified on the command line
                if (variableField == null)
                {
                    variableField = ResolveFromCollection(name, m_assumedGlobals, FieldType.Global, false);
                }

                // if it's not something explicitly defined so far, check to see if it
                // matches the browser-specific pattern (prefixes followed by Pascal-cased identifiers).
                // Plus, most browsers expose dozens of DOM elements prefixed by "HTML"
                // (eg: HTMLAnchorElement and HTMLTableColElement).
                if (variableField == null && s_blanketPrefixes.IsMatch(name))
                {
                    variableField = new JSVariableField(FieldType.Predefined, name, 0, null);
                    AddField(variableField);
                }

                return(variableField);
            }
        }
Example #6
0
        private static SourceContext GetFirstDeclaration(JSVariableField variableField)
        {
            // only local fields that actually correspond to a declaration get the declaration
            // added to the declarations collection -- inner references don't get the declaration,
            // and neither do ghosted variables. So starting from this variable, walk up the
            // outer-reference chain until we find on with at least one declaration. If we don't
            // find one, that's fine -- there probably isn't a declaration for it (predefined, for example).
            while (variableField != null && variableField.Declarations.Count == 0)
            {
                variableField = variableField.OuterField;
            }

            if (variableField != null)
            {
                foreach (var declaration in variableField.Declarations)
                {
                    // we only care about the FIRST declaration, so return the context of the name
                    return(declaration.Context);
                }
            }

            // if we get here, there were no declarations
            return(null);
        }
Example #7
0
 public override JSVariableField CreateField(JSVariableField outerField)
 {
     // when we create a field inside a with-scope, it's ALWAYS a with-field, no matter
     // what type the outer reference is.
     return(new JSVariableField(FieldType.WithField, outerField));
 }
Example #8
0
 public override JSVariableField CreateField(JSVariableField outerField)
 {
     // should NEVER try to create an inner field in a global scope
     throw new NotImplementedException();
 }
Example #9
0
 public JSNamedFunctionExpressionField(JSVariableField variableField)
     : base(variableField)
 {
     CanCrunch  = true;
     IsFunction = true;
 }
Example #10
0
        private void ProcessField(JSVariableField field, bool isDefined)
        {
            // save THIS field's refcount value because we will
            // be adjusting hte field pointer to be the outermost field
            // and we want to report THIS field's refcount, not the overall.
            var refCount = field.RefCount;
            var isGhost  = false;

            // make sure we're at the outer-most field
            var isOuter = false;

            if (!isDefined)
            {
                while (field.OuterField != null)
                {
                    isOuter = true;
                    field   = field.OuterField;
                }
            }

            m_writer.WriteStartElement("field");

            if (field.IsExported)
            {
                m_writer.WriteAttributeString("exported", "true");
            }

            var typeValue = field.FieldType.ToString();

            switch (field.FieldType)
            {
            case FieldType.Argument:
            case FieldType.CatchError:
            case FieldType.WithField:
                if (isOuter)
                {
                    typeValue = "Outer " + typeValue;
                }
                break;

            case FieldType.Local:
                if (isOuter)
                {
                    typeValue = "Outer ";
                }
                else
                {
                    typeValue = string.Empty;
                    if (field.IsPlaceholder || !field.IsDeclared)
                    {
                        isGhost = true;
                    }
                }

                if (field.IsFunction)
                {
                    typeValue += "Function";
                }
                else
                {
                    typeValue += "Variable";
                }
                break;

            case FieldType.Arguments:
            case FieldType.Global:
            case FieldType.UndefinedGlobal:
            case FieldType.GhostCatch:
            case FieldType.GhostFunction:
            case FieldType.Predefined:
            case FieldType.Super:
                break;
            }

            m_writer.WriteAttributeString("type", typeValue.ToLowerInvariant());
            m_writer.WriteAttributeString("src", field.Name);
            if (field.CrunchedName != null)
            {
                m_writer.WriteAttributeString("min", field.CrunchedName);
            }

            OutputContextPosition(field.OriginalContext);

            if (m_useReferenceCounts)
            {
                m_writer.WriteAttributeString("refcount", refCount.ToStringInvariant());
            }

            if (field.IsAmbiguous)
            {
                m_writer.WriteAttributeString("ambiguous", "true");
            }

            if (field.IsGenerated)
            {
                m_writer.WriteAttributeString("generated", "true");
            }

            if (isGhost)
            {
                m_writer.WriteAttributeString("ghost", "true");
            }

            m_writer.WriteEndElement();
        }
Example #11
0
 public JSNamedFunctionExpressionField(JSVariableField variableField)
     : base(variableField)
 {
     CanCrunch = true;
     IsFunction = true;
 }
Example #12
0
        private static void GetFieldScopeType(JSVariableField variableField, out string scope, out string type)
        {
            // default scope is blank
            scope = string.Empty;
            switch (variableField.FieldType)
            {
            case FieldType.Argument:
                type = NUglify.MemberInfoTypeArgument;
                if (variableField.IsOuterReference)
                {
                    scope = NUglify.MemberInfoScopeOuter;
                }
                break;

            case FieldType.Arguments:
                type = NUglify.MemberInfoTypeArguments;
                if (variableField.IsOuterReference)
                {
                    scope = NUglify.MemberInfoScopeOuter;
                }
                break;

            case FieldType.CatchError:
                type = NUglify.MemberInfoTypeCatchEror;
                if (variableField.IsOuterReference)
                {
                    scope = NUglify.MemberInfoScopeOuter;
                }
                break;

            case FieldType.Super:
                type = NUglify.MemberInfoTypeSuper;
                if (variableField.IsOuterReference)
                {
                    scope = NUglify.MemberInfoScopeOuter;
                }
                break;

            case FieldType.GhostCatch:
            case FieldType.GhostFunction:
            default:
                // ghost fields -- ignore
                type = string.Empty;
                break;

            case FieldType.Global:
            case FieldType.UndefinedGlobal:
                if ((variableField.Attributes & FieldAttributes.RTSpecialName) == FieldAttributes.RTSpecialName)
                {
                    // this is a special "global." It might not be a global, but something referenced
                    // in a with scope somewhere down the line.
                    type = NUglify.MemberInfoPossiblyUndefined;
                }
                else if (variableField.FieldValue is FunctionObject && variableField.GhostedField != null)
                {
                    type = NUglify.MemberInfoFunctionExpression;
                }
                else
                {
                    goto case FieldType.Local;
                }
                break;

            case FieldType.Local:
                // type string
                if (variableField.FieldValue is FunctionObject)
                {
                    if (variableField.GhostedField == null)
                    {
                        type = NUglify.MemberInfoFunction;
                    }
                    else
                    {
                        type = NUglify.MemberInfoFunctionExpression;
                    }
                }
                else if (variableField.FieldValue is ClassNode)
                {
                    type = NUglify.MemberInfoClass;
                }
                else if (variableField.IsLiteral)
                {
                    type = NUglify.MemberInfoLiteral;
                }
                else if (variableField.InitializationOnly)
                {
                    type = NUglify.MemberInfoConst;
                }
                else
                {
                    type = NUglify.MemberInfoVar;
                }

                // scope string
                if (variableField.IsOuterReference)
                {
                    scope = NUglify.MemberInfoScopeOuter;
                }
                else if (variableField.FieldType == FieldType.Global || variableField.FieldType == FieldType.UndefinedGlobal)
                {
                    scope = NUglify.MemberInfoScopeGlobal;
                }
                else
                {
                    scope = NUglify.MemberInfoScopeLocal;
                }
                break;

            case FieldType.Predefined:
                scope = NUglify.MemberInfoScopeGlobalObject;
                type  = variableField.IsFunction
                        ? NUglify.MemberInfoBuiltInMethod
                        : NUglify.MemberInfoBuiltInProperty;
                break;

            case FieldType.WithField:
                type = NUglify.MemberInfoWithField;
                if (variableField.IsOuterReference)
                {
                    scope = NUglify.MemberInfoScopeOuter;
                }
                break;
            }

            if (variableField.IsExported)
            {
                scope = NUglify.MemberInfoScopeExported + scope;
            }
        }
Example #13
0
        // NAME [SCOPE TYPE] [crunched to CRUNCH]
        //
        // SCOPE: global, local, outer, ''
        // TYPE: var, function, argument, arguments array, possibly undefined
        private void WriteMemberReport(JSVariableField variableField)
        {
            // don't report arguments fields that aren't referenced because
            // we add those fields to the function scopes automatically
            if (variableField.FieldType != FieldType.Arguments || variableField.RefCount > 0)
            {
                string scope    = string.Empty;
                string type     = string.Empty;
                string crunched = string.Empty;
                string name     = variableField.Name;
                if (variableField.IsLiteral)
                {
                    name = variableField.FieldValue.ToString();
                }

                // calculate the crunched label
                if (variableField.CrunchedName != null)
                {
                    crunched = NUglify.CrunchedTo.FormatInvariant(variableField.CrunchedName, variableField.RefCount);
                }
                else
                {
                    crunched = NUglify.MemberInfoReferences.FormatInvariant(variableField.RefCount);
                }

                // get the field's default scope and type
                GetFieldScopeType(variableField, out scope, out type);
                if (variableField.FieldType == FieldType.WithField)
                {
                    // if the field is a with field, we won't be using the crunched field (since
                    // those fields can't be crunched), so let's overload it with what the field
                    // could POSSIBLY be if the with object doesn't have a property of that name
                    if (variableField.OuterField != null)
                    {
                        // make sure we get the OUTERMOST outer ield
                        var outerField = variableField.OuterField;
                        while (outerField.OuterField != null)
                        {
                            outerField = outerField.OuterField;
                        }

                        string outerScope;
                        string outerType;
                        GetFieldScopeType(outerField, out outerScope, out outerType);
                        if (!outerScope.IsNullOrWhiteSpace() || !outerType.IsNullOrWhiteSpace())
                        {
                            crunched = NUglify.MemberInfoWithPossibly.FormatInvariant(outerScope, outerType);
                        }
                    }
                    else
                    {
                        // no outer field. Then it must be a lexically-declared field inside the with-statement's
                        // block. These are tricky! At run-time if you try to declare a function, const, or let
                        // inside the with-scope, and the with-object already has a property with that name, the
                        // declaration will throw a run-time error.
                        crunched = variableField.IsFunction ? NUglify.MemberInfoWithLexFunc : NUglify.MemberInfoWithLexDecl;
                    }
                }

                var definedLocation = string.Empty;
                var definedContext  = GetFirstDeclaration(variableField);
                if (definedContext != null)
                {
                    definedLocation = NUglify.MemberInfoDefinedLocation.FormatInvariant(definedContext.StartLineNumber, definedContext.StartColumn + 1);
                }

                // format the entire string
                WriteProgress(NUglify.MemberInfoFormat.FormatInvariant(
                                  name,
                                  scope,
                                  type,
                                  crunched,
                                  definedLocation
                                  ));
            }
        }