private void DefineField(ResolutionVisitor resolutionVisitor, INameDeclaration nameDecl) { if (nameDecl == null) { // malformed code, for example catch w/o a variable. return; } var field = this[nameDecl.Name]; if (nameDecl is ParameterDeclaration) { // function parameters are handled separately, so if this is a parameter declaration, // then it must be a catch variable. if (field == null) { // no collision - create the catch-error field field = new JSVariableField(FieldType.CatchError, nameDecl.Name); this.AddField(field); } else { // it's an error to declare anything in the catch scope with the same name as the // error variable ErrorSink.HandleError(JSError.DuplicateCatch, nameDecl.GetNameSpan(GlobalScope.Node.LocationResolver), resolutionVisitor._locationResolver, true); } } else { if (field == null) { // could be global or local depending on the scope, so let the scope create it. field = this.CreateField(nameDecl.Name); // if this field is a constant, mark it now var lexDeclaration = nameDecl.Parent as LexicalDeclaration; this.AddField(field); } else { // already defined! // if this is a lexical declaration, then it's an error because we have two // lexical declarations with the same name in the same scope. if (nameDecl.Parent is LexicalDeclaration) { _errorSink.HandleError( JSError.DuplicateLexicalDeclaration, nameDecl.GetNameSpan(GlobalScope.Node.LocationResolver), resolutionVisitor._locationResolver, true ); } } } nameDecl.VariableField = field; }
private void DefineField(INameDeclaration nameDecl, FunctionObject fieldValue) { var field = this[nameDecl.Name]; if (nameDecl is ParameterDeclaration) { // function parameters are handled separately, so if this is a parameter declaration, // then it must be a catch variable. if (field == null) { // no collision - create the catch-error field field = new JSVariableField(FieldType.CatchError, nameDecl.Name, 0, null) { OriginalContext = nameDecl.NameContext.Clone(), IsDeclared = true }; this.AddField(field); } else { // it's an error to declare anything in the catch scope with the same name as the // error variable field.OriginalContext.HandleError(JSError.DuplicateCatch, true); } } else { if (field == null) { // could be global or local depending on the scope, so let the scope create it. field = this.CreateField(nameDecl.Name, null, 0); field.OriginalContext = nameDecl.NameContext.Clone(); field.IsDeclared = true; field.IsFunction = (nameDecl is FunctionObject); field.FieldValue = fieldValue; // if this field is a constant, mark it now var lexDeclaration = nameDecl.Parent as LexicalDeclaration; field.InitializationOnly = nameDecl.Parent is ConstStatement || (lexDeclaration != null && lexDeclaration.StatementToken == JSToken.Const); this.AddField(field); } else { // already defined! // if this is a lexical declaration, then it's an error because we have two // lexical declarations with the same name in the same scope. if (nameDecl.Parent is LexicalDeclaration) { nameDecl.NameContext.HandleError(JSError.DuplicateLexicalDeclaration, true); } if (nameDecl.Initializer != null) { // if this is an initialized declaration, then the var part is // superfluous and the "initializer" is really a lookup assignment. // So bump up the ref-count for those cases. var nameReference = nameDecl as INameReference; if (nameReference != null) { field.AddReference(nameReference); } } // don't clobber an existing field value with null. For instance, the last // function declaration is the winner, so always set the value if we have something, // but a var following a function shouldn't reset it to null. if (fieldValue != null) { field.FieldValue = fieldValue; } } } nameDecl.VariableField = field; field.Declarations.Add(nameDecl); // if this scope is within a with-statement, or if the declaration was flagged // as not being renamable, then mark the field as not crunchable if (IsInWithScope || nameDecl.RenameNotAllowed) { field.CanCrunch = false; } }