Exemplo n.º 1
0
        internal override void AnalyzeScope()
        {
            if (Context != null)
            {
                // get the parent global/function scope where variables defined within our
                // scope are REALLY defined
                ActivationObject definingScope = this;
                do
                {
                    definingScope = definingScope.Parent;
                } while (definingScope is BlockScope);

                // see if there is a variable already defined in that scope with the same name
                JSVariableField outerField = definingScope[m_name];
                if (outerField != null)
                {
                    // there is one defined already!!!
                    // but if it isn't referenced, it's safe to just use it
                    // as the outer field for our catch variable so our names
                    // stay in sync when we rename stuff
                    if (outerField.IsReferenced)
                    {
                        // but the outer field IS referenced somewhere! We have a possible ambiguous
                        // catch variable problem that behaves differently in IE and non-IE browsers.
                        Context.HandleError(JSError.AmbiguousCatchVar);
                    }
                }
                else
                {
                    // there isn't one defined -- add one and hook it to our argument
                    // field as the outer reference so the name doesn't collide with any
                    // other fields in that scope if we are renaming fields
                    outerField = definingScope.CreateField(m_name, null, 0);
                    outerField.IsPlaceholder = true;
                    definingScope.AddField(outerField);
                }

                // point our inner catch variable to the outer variable
                this[m_name].OuterField = outerField;
            }
            base.AnalyzeScope();
        }
Exemplo n.º 2
0
        internal override void AnalyzeNode()
        {
            // figure out if our reference type is a function or a constructor
            if (Parent is CallNode)
            {
                m_refType = (
                    ((CallNode)Parent).IsConstructor
                  ? ReferenceType.Constructor
                  : ReferenceType.Function
                    );
            }

            ActivationObject scope = ScopeStack.Peek();

            VariableField = scope.FindReference(m_name);
            if (VariableField == null)
            {
                // this must be a global. if it isn't in the global space, throw an error
                // this name is not in the global space.
                // if it isn't generated, then we want to throw an error
                // we also don't want to report an undefined variable if it is the object
                // of a typeof operator
                if (!m_isGenerated && !(Parent is TypeOfNode))
                {
                    // report this undefined reference
                    Context.ReportUndefined(this);

                    // possibly undefined global (but definitely not local)
                    Context.HandleError(
                        (Parent is CallNode && ((CallNode)Parent).Function == this ? JSError.UndeclaredFunction : JSError.UndeclaredVariable),
                        null,
                        false
                        );
                }

                if (!(scope is GlobalScope))
                {
                    // add it to the scope so we know this scope references the global
                    scope.AddField(new JSGlobalField(
                                       m_name,
                                       Missing.Value,
                                       0
                                       ));
                }
            }
            else
            {
                // BUT if this field is a place-holder in the containing scope of a named
                // function expression, then we need to throw an ambiguous named function expression
                // error because this could cause problems.
                // OR if the field is already marked as ambiguous, throw the error
                if (VariableField.NamedFunctionExpression != null ||
                    VariableField.IsAmbiguous)
                {
                    // mark it as a field that's referenced ambiguously
                    VariableField.IsAmbiguous = true;
                    // throw as an error
                    Context.HandleError(JSError.AmbiguousNamedFunctionExpression, true);

                    // if we are preserving function names, then we need to mark this field
                    // as not crunchable
                    if (Parser.Settings.PreserveFunctionNames)
                    {
                        VariableField.CanCrunch = false;
                    }
                }

                // see if this scope already points to this name
                if (scope[m_name] == null)
                {
                    // create an inner reference so we don't keep walking up the scope chain for this name
                    VariableField = scope.CreateInnerField(VariableField);
                }

                // add the reference
                VariableField.AddReference(scope);

                if (VariableField is JSPredefinedField)
                {
                    // this is a predefined field. If it's Nan or Infinity, we should
                    // replace it with the numeric value in case we need to later combine
                    // some literal expressions.
                    if (string.CompareOrdinal(m_name, "NaN") == 0)
                    {
                        // don't analyze the new ConstantWrapper -- we don't want it to take part in the
                        // duplicate constant combination logic should it be turned on.
                        Parent.ReplaceChild(this, new ConstantWrapper(double.NaN, PrimitiveType.Number, Context, Parser));
                    }
                    else if (string.CompareOrdinal(m_name, "Infinity") == 0)
                    {
                        // don't analyze the new ConstantWrapper -- we don't want it to take part in the
                        // duplicate constant combination logic should it be turned on.
                        Parent.ReplaceChild(this, new ConstantWrapper(double.PositiveInfinity, PrimitiveType.Number, Context, Parser));
                    }
                }
            }
        }