internal FunctionObject(string name, ParameterDeclaration[] parameter_declarations, TypeExpression return_type_expr, Block body, FunctionScope own_scope, ScriptObject enclosing_scope, Context funcContext, MethodAttributes attributes, CustomAttributeList customAttributes, bool isMethod) : base(body.Globals.globalObject.originalFunction.originalPrototype, name, parameter_declarations.Length) { this.parameter_declarations = parameter_declarations; int length = parameter_declarations.Length; this.formal_parameters = new string[length]; for (int i = 0; i < length; i++) { this.formal_parameters[i] = parameter_declarations[i].identifier; } this.argumentsSlotNumber = 0; this.return_type_expr = return_type_expr; if (this.return_type_expr != null) { own_scope.AddReturnValueField(); } this.body = body; this.method = null; this.parameterInfos = null; this.funcContext = funcContext; this.own_scope = own_scope; this.own_scope.owner = this; if ((!(enclosing_scope is ActivationObject) || !((ActivationObject) enclosing_scope).fast) && !isMethod) { this.argumentsSlotNumber = this.own_scope.GetNextSlotNumber(); JSLocalField field = (JSLocalField) this.own_scope.AddNewField("arguments", null, FieldAttributes.PrivateScope); field.type = new TypeExpression(new ConstantWrapper(Typeob.Object, funcContext)); field.isDefined = true; this.hasArgumentsObject = true; } else { this.hasArgumentsObject = false; } this.implementedIface = null; this.implementedIfaceMethod = null; this.isMethod = isMethod; this.isExpandoMethod = (customAttributes != null) && customAttributes.ContainsExpandoAttribute(); this.isStatic = this.own_scope.isStatic = (attributes & MethodAttributes.Static) != MethodAttributes.PrivateScope; this.suppressIL = false; this.noVersionSafeAttributeSpecified = true; this.fields = this.own_scope.GetLocalFields(); this.enclosing_scope = enclosing_scope; this.must_save_stack_locals = false; this.text = null; this.mb = null; this.cb = null; this.attributes = attributes; if (!this.isStatic) { this.attributes |= MethodAttributes.HideBySig; } this.globals = body.Globals; this.superConstructor = null; this.superConstructorCall = null; this.customAttributes = customAttributes; base.noExpando = false; this.clsCompliance = CLSComplianceSpec.NotAttributed; this.engineLocal = null; this.partiallyEvaluated = false; }
internal FunctionExpression(Context context, AST id, ParameterDeclaration[] formal_parameters, TypeExpression return_type, Block body, FunctionScope own_scope, FieldAttributes attributes) : base(context){ if (attributes != (FieldAttributes)0){ this.context.HandleError(JSError.SyntaxError); attributes = (FieldAttributes)0; } ScriptObject enclosingScope = Globals.ScopeStack.Peek(); this.name = id.ToString(); if (this.name.Length == 0) this.name = "anonymous "+(uniqueNumber++).ToString(CultureInfo.InvariantCulture); else this.AddNameTo(enclosingScope); this.func = new FunctionObject(this.name, formal_parameters, return_type, body, own_scope, enclosingScope, this.context, MethodAttributes.Static|MethodAttributes.Public); }
internal FunctionObject(string name, ParameterDeclaration[] parameter_declarations, TypeExpression return_type_expr, Block body, FunctionScope own_scope, ScriptObject enclosing_scope, Context funcContext, MethodAttributes attributes) : this(name, parameter_declarations, return_type_expr, body, own_scope, enclosing_scope, funcContext, attributes, null, false) { }
internal FunctionDeclaration(Context context, AST ifaceId, IdentifierLiteral id, ParameterDeclaration[] formal_parameters, TypeExpression return_type, Block body, FunctionScope own_scope, FieldAttributes attributes, bool isMethod, bool isGetter, bool isSetter, bool isAbstract, bool isFinal, CustomAttributeList customAttributes) : base(context) { MethodAttributes methodAttributes = (MethodAttributes)0; if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public) methodAttributes = MethodAttributes.Public; else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private) methodAttributes = MethodAttributes.Private; else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly) methodAttributes = MethodAttributes.Assembly; else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family) methodAttributes = MethodAttributes.Family; else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem) methodAttributes = MethodAttributes.FamORAssem; else methodAttributes = MethodAttributes.Public; if ((attributes & FieldAttributes.Static) != 0 || !isMethod) methodAttributes |= MethodAttributes.Static; else methodAttributes |= MethodAttributes.Virtual | MethodAttributes.NewSlot; if (isAbstract) methodAttributes |= MethodAttributes.Abstract; if (isFinal) methodAttributes |= MethodAttributes.Final; this.name = id.ToString(); this.isMethod = isMethod; if (ifaceId != null){ if (isMethod){ this.ifaceId = new TypeExpression(ifaceId); methodAttributes &= ~MethodAttributes.MemberAccessMask; methodAttributes |= MethodAttributes.Private|MethodAttributes.Final; }else{ this.declaringObject = new Member(ifaceId.context, ifaceId, id); this.name = this.declaringObject.ToString(); } } ScriptObject enclosingScope = Globals.ScopeStack.Peek(); if (attributes == 0 && !isAbstract && !isFinal){ if (enclosingScope is ClassScope) attributes |= FieldAttributes.Public; }else{ if (!(enclosingScope is ClassScope)){ this.context.HandleError(JSError.NotInsideClass); attributes = (FieldAttributes)0; methodAttributes = MethodAttributes.Public; } } if (enclosingScope is ActivationObject){ this.inFastScope = ((ActivationObject)enclosingScope).fast; // if later on originalName != this.name this is a property getter/setter String originalName = this.name; // mangle the name if (isGetter){ methodAttributes |= MethodAttributes.SpecialName; this.name = "get_" + this.name; if (return_type == null) return_type = new TypeExpression(new ConstantWrapper(Typeob.Object, context)); }else if (isSetter){ methodAttributes |= MethodAttributes.SpecialName; this.name = "set_" + this.name; return_type = new TypeExpression(new ConstantWrapper(Typeob.Void, context)); } attributes &= FieldAttributes.FieldAccessMask; // create the function object this.func = new FunctionObject(this.name, formal_parameters, return_type, body, own_scope, enclosingScope, this.context, methodAttributes, customAttributes, this.isMethod); if (this.declaringObject != null) return; // check whether the function name (possibly mangled) is in use already String fieldName = this.name; if (this.ifaceId != null) fieldName = ifaceId.ToString()+"."+fieldName; JSVariableField localField = (JSVariableField)((ActivationObject)enclosingScope).name_table[fieldName]; if (localField != null && (!(localField is JSMemberField) || !(((JSMemberField)localField).value is FunctionObject) || this.func.isExpandoMethod)){ if (originalName != this.name) localField.originalContext.HandleError(JSError.ClashWithProperty); else{ id.context.HandleError(JSError.DuplicateName, this.func.isExpandoMethod); if (localField.value is FunctionObject) ((FunctionObject)localField.value).suppressIL = true; } } // create or update the proper field if (this.isMethod){ if (!(localField is JSMemberField) || !(((JSMemberField)localField).value is FunctionObject) || originalName != this.name){ this.field = ((ActivationObject)enclosingScope).AddNewField(fieldName, this.func, attributes|FieldAttributes.Literal); if (originalName == this.name) // if it is a property do not assign the type ((JSVariableField)this.field).type = new TypeExpression(new ConstantWrapper(Typeob.FunctionWrapper, this.context)); }else this.field = ((JSMemberField)localField).AddOverload(this.func, attributes|FieldAttributes.Literal); }else if (enclosingScope is FunctionScope){ if (this.inFastScope) attributes |= FieldAttributes.Literal; this.field = ((FunctionScope)enclosingScope).AddNewField(this.name, attributes, this.func); if (this.field is JSLocalField){ JSLocalField locField = (JSLocalField)this.field; if (this.inFastScope){ locField.type = new TypeExpression(new ConstantWrapper(Typeob.ScriptFunction, this.context)); locField.attributeFlags |= FieldAttributes.Literal; } locField.debugOn = this.context.document.debugOn; locField.isDefined = true; } }else if (this.inFastScope){ this.field = ((ActivationObject)enclosingScope).AddNewField(this.name, this.func, attributes|FieldAttributes.Literal); ((JSVariableField)this.field).type = new TypeExpression(new ConstantWrapper(Typeob.ScriptFunction, this.context)); //Do not use typeof(Closure) for the field, since that has the arguments and callee properties, which are not //accessible in fast mode }else //enclosingScope is GlobalObject this.field = ((ActivationObject)enclosingScope).AddNewField(this.name, this.func, attributes|FieldAttributes.Static); ((JSVariableField)this.field).originalContext = context; // if it is a property create/update the PropertyInfo and assign the getter/setter if (originalName != this.name){ String propertyFieldName = originalName; if (this.ifaceId != null) propertyFieldName = ifaceId.ToString()+"."+originalName; FieldInfo prop = (FieldInfo)((ClassScope)enclosingScope).name_table[propertyFieldName]; if (prop != null){ // check whether a property was defined already if (prop.IsLiteral){ Object val = ((JSVariableField)prop).value; if (val is JSProperty) this.enclosingProperty = (JSProperty)val; } if (this.enclosingProperty == null) id.context.HandleError(JSError.DuplicateName, true); // the matching name was not a property } if (this.enclosingProperty == null){ this.enclosingProperty = new JSProperty(originalName); prop = ((ActivationObject)enclosingScope).AddNewField(propertyFieldName, this.enclosingProperty, attributes|FieldAttributes.Literal); ((JSMemberField)prop).originalContext = this.context; }else{ if ((isGetter && this.enclosingProperty.getter != null) || (isSetter && this.enclosingProperty.setter != null)) id.context.HandleError(JSError.DuplicateName, true); // duplicated setter or getter } if (isGetter) this.enclosingProperty.getter = new JSFieldMethod(this.field, enclosingScope); else this.enclosingProperty.setter = new JSFieldMethod(this.field, enclosingScope); } }else{ //Might get here if function declaration is inside of an eval. this.inFastScope = false; this.func = new FunctionObject(this.name, formal_parameters, return_type, body, own_scope, enclosingScope, this.context, MethodAttributes.Public, null, false); this.field = ((StackFrame)enclosingScope).AddNewField(this.name, new Closure(this.func), attributes|FieldAttributes.Static); } }
private AST ParseFunction(FieldAttributes visibilitySpec, bool inExpression, Context fncCtx, bool isMethod, bool isAbstract, bool isFinal, bool isInterface, CustomAttributeList customAttributes, Call function){ IdentifierLiteral name = null; AST interfaceName = null; ArrayList formalParameters = null; TypeExpression returnType = null; Block body = null; bool isGetter = false; bool isSetter = false; if (function == null){ GetNextToken(); if (isMethod) if (JSToken.Get == this.currentToken.token){ isGetter = true; GetNextToken(); }else if (JSToken.Set == this.currentToken.token){ isSetter = true; GetNextToken(); } // get the function name or make an anonymous function if in expression "position" if (JSToken.Identifier == this.currentToken.token){ name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); if (JSToken.AccessField == this.currentToken.token){ if (isInterface) // "function IBar.foo()" is illegal in an interface declaration ReportError(JSError.SyntaxError, true); GetNextToken(); if (JSToken.Identifier == this.currentToken.token){ interfaceName = new Lookup(name.context); name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); while (JSToken.AccessField == this.currentToken.token){ GetNextToken(); if (JSToken.Identifier == this.currentToken.token){ interfaceName = new Member(interfaceName.context.CombineWith(this.currentToken), interfaceName, new ConstantWrapper(name.ToString(), name.context)); name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); }else ReportError(JSError.NoIdentifier, true); } }else ReportError(JSError.NoIdentifier, true); } }else{ string identifier = JSKeyword.CanBeIdentifier(this.currentToken.token); if (null != identifier){ ForceReportInfo(JSError.KeywordUsedAsIdentifier, isMethod); name = new IdentifierLiteral(identifier, this.currentToken.Clone()); GetNextToken(); }else{ if (!inExpression){ identifier = this.currentToken.GetCode(); ReportError(JSError.NoIdentifier, true); GetNextToken(); }else identifier = ""; name = new IdentifierLiteral(identifier, CurrentPositionContext()); } } }else{ // function was passed in, this is an error condition name = function.GetName(); } // make a new state and save the old one ArrayList blockType = this.blockType; this.blockType = new ArrayList(16); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(16); FunctionScope fscope = new FunctionScope(Globals.ScopeStack.Peek(), isMethod); Globals.ScopeStack.Push(fscope); //Give declarations a place to go while building AST try{ formalParameters = new ArrayList(); Context paramArrayContext = null; if (function == null){ // get the formal parameters if (JSToken.LeftParen != this.currentToken.token) ReportError(JSError.NoLeftParen); GetNextToken(); // create the list of arguments and update the context while (JSToken.RightParen != this.currentToken.token){ if (paramArrayContext != null){ ReportError(JSError.ParamListNotLast, paramArrayContext, true); paramArrayContext = null; } String id = null; TypeExpression typeExpr = null; this.noSkipTokenSet.Add(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); try{ if (JSToken.ParamArray == this.currentToken.token){ paramArrayContext = this.currentToken.Clone(); GetNextToken(); } if (JSToken.Identifier != this.currentToken.token && (id = JSKeyword.CanBeIdentifier(this.currentToken.token)) == null){ if (JSToken.LeftCurly == this.currentToken.token){ ReportError(JSError.NoRightParen); break; }else if (JSToken.Comma == this.currentToken.token){ // We're missing an argument (or previous argument was malformed and // we skipped to the comma.) Keep trying to parse the argument list -- // we will skip the comma below. ReportError(JSError.SyntaxError, true); }else{ ReportError(JSError.SyntaxError, true); SkipTokensAndThrow(); } }else{ if (null == id) id = this.scanner.GetIdentifier(); else ForceReportInfo(JSError.KeywordUsedAsIdentifier); Context paramCtx = this.currentToken.Clone(); GetNextToken(); if (JSToken.Colon == this.currentToken.token){ typeExpr = ParseTypeExpression(); if (null != typeExpr) paramCtx.UpdateWith(typeExpr.context); } CustomAttributeList custAttrs = null; if (paramArrayContext != null){ custAttrs = new CustomAttributeList(paramArrayContext); custAttrs.Append(new CustomAttribute(paramArrayContext, new Lookup("...", paramArrayContext), new ASTList(null))); } formalParameters.Add(new ParameterDeclaration(paramCtx, id, typeExpr, custAttrs)); } // got an arg, it should be either a ',' or ')' if (JSToken.RightParen == this.currentToken.token) break; else if (JSToken.Comma != this.currentToken.token){ // deal with error in some "intelligent" way if (JSToken.LeftCurly == this.currentToken.token){ ReportError(JSError.NoRightParen); break; }else{ if (JSToken.Identifier == this.currentToken.token && typeExpr == null){ // it's possible that the guy was writing the type in C/C++ style (i.e. int x) ReportError(JSError.NoCommaOrTypeDefinitionError); }else ReportError(JSError.NoComma); } } GetNextToken(); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet, exc) == -1) throw exc; }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); } } fncCtx.UpdateWith(this.currentToken); // if it is a getter/setter must have 0/1 arg only if (isGetter && formalParameters.Count != 0){ ReportError(JSError.BadPropertyDeclaration, true); isGetter = false; }else if (isSetter && formalParameters.Count != 1){ ReportError(JSError.BadPropertyDeclaration, true); isSetter = false; } GetNextToken(); // check the return type if (JSToken.Colon == this.currentToken.token){ if (isSetter) ReportError(JSError.SyntaxError); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); try{ returnType = ParseTypeExpression(); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_StartBlockNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = null; throw exc; }else{ if (exc._partiallyComputedNode != null) returnType = (TypeExpression)exc._partiallyComputedNode; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); } if (isSetter) returnType = null; } }else{ // function was passed in, this is an error condition function.GetParameters(formalParameters); } // read the function body of non-abstract functions. if (JSToken.LeftCurly != this.currentToken.token && (isAbstract || (isMethod && GuessIfAbstract()))){ if (!isAbstract){ isAbstract = true; ReportError(JSError.ShouldBeAbstract, fncCtx, true); } body = new Block(this.currentToken.Clone()); }else{ if (JSToken.LeftCurly != this.currentToken.token) ReportError(JSError.NoLeftCurly, true); else if (isAbstract) ReportError(JSError.AbstractWithBody, fncCtx, true); this.blockType.Add(BlockType.Block); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try{ // parse the block locally to get the exact end of function body = new Block(this.currentToken.Clone()); GetNextToken(); while (JSToken.RightCurly != this.currentToken.token){ try{ body.Append(ParseStatement()); }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null){ body.Append(exc._partiallyComputedNode); } if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1) throw exc; } } body.context.UpdateWith(this.currentToken); fncCtx.UpdateWith(this.currentToken); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){ Globals.ScopeStack.Pop(); //Pop current scope so that FunctionDeclaration sees proper scope stack try{ ParameterDeclaration[] foParameters = new ParameterDeclaration[formalParameters.Count]; formalParameters.CopyTo(foParameters); if (inExpression) exc._partiallyComputedNode = new FunctionExpression(fncCtx, name, foParameters, returnType, body, fscope, visibilitySpec); else exc._partiallyComputedNode = new FunctionDeclaration(fncCtx, interfaceName, name, foParameters, returnType, body, fscope, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); if (customAttributes != null) customAttributes.SetTarget(exc._partiallyComputedNode); }finally{ Globals.ScopeStack.Push(fscope); //Push it back so that the next finally can pop it } throw exc; } }finally{ this.blockType.RemoveAt(this.blockType.Count - 1); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } GetNextToken(); } }finally{ // restore state this.blockType = blockType; this.labelTable = labelTable; Globals.ScopeStack.Pop(); } ParameterDeclaration[] fParameters = new ParameterDeclaration[formalParameters.Count]; formalParameters.CopyTo(fParameters); AST func; if (inExpression) func = new FunctionExpression(fncCtx, name, fParameters, returnType, body, fscope, visibilitySpec); else func = new FunctionDeclaration(fncCtx, interfaceName, name, fParameters, returnType, body, fscope, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); if (customAttributes != null) customAttributes.SetTarget(func); return func; }
internal FunctionDeclaration(Context context, AST ifaceId, IdentifierLiteral id, ParameterDeclaration[] formal_parameters, TypeExpression return_type, Block body, FunctionScope own_scope, FieldAttributes attributes, bool isMethod, bool isGetter, bool isSetter, bool isAbstract, bool isFinal, CustomAttributeList customAttributes) : base(context) { this.completion = new Completion(); MethodAttributes privateScope = MethodAttributes.PrivateScope; if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public) { privateScope = MethodAttributes.Public; } else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private) { privateScope = MethodAttributes.Private; } else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly) { privateScope = MethodAttributes.Assembly; } else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family) { privateScope = MethodAttributes.Family; } else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem) { privateScope = MethodAttributes.FamORAssem; } else { privateScope = MethodAttributes.Public; } if (((attributes & FieldAttributes.Static) != FieldAttributes.PrivateScope) || !isMethod) { privateScope |= MethodAttributes.Static; } else { privateScope |= MethodAttributes.NewSlot | MethodAttributes.Virtual; } if (isAbstract) { privateScope |= MethodAttributes.Abstract; } if (isFinal) { privateScope |= MethodAttributes.Final; } this.name = id.ToString(); this.isMethod = isMethod; if (ifaceId != null) { if (isMethod) { this.ifaceId = new TypeExpression(ifaceId); privateScope &= ~MethodAttributes.MemberAccessMask; privateScope |= MethodAttributes.Final | MethodAttributes.Private; } else { this.declaringObject = new Member(ifaceId.context, ifaceId, id); this.name = this.declaringObject.ToString(); } } ScriptObject obj2 = base.Globals.ScopeStack.Peek(); if (((attributes == FieldAttributes.PrivateScope) && !isAbstract) && !isFinal) { if (obj2 is ClassScope) { attributes |= FieldAttributes.Public; } } else if (!(obj2 is ClassScope)) { base.context.HandleError(JSError.NotInsideClass); attributes = FieldAttributes.PrivateScope; privateScope = MethodAttributes.Public; } if (obj2 is ActivationObject) { this.inFastScope = ((ActivationObject) obj2).fast; string name = this.name; if (isGetter) { privateScope |= MethodAttributes.SpecialName; this.name = "get_" + this.name; if (return_type == null) { return_type = new TypeExpression(new ConstantWrapper(Typeob.Object, context)); } } else if (isSetter) { privateScope |= MethodAttributes.SpecialName; this.name = "set_" + this.name; return_type = new TypeExpression(new ConstantWrapper(Typeob.Void, context)); } attributes &= FieldAttributes.FieldAccessMask; MethodAttributes attributes3 = privateScope & MethodAttributes.MemberAccessMask; if ((((privateScope & MethodAttributes.Virtual) != MethodAttributes.PrivateScope) && ((privateScope & MethodAttributes.Final) == MethodAttributes.PrivateScope)) && (((attributes3 == MethodAttributes.Private) || (attributes3 == MethodAttributes.Assembly)) || (attributes3 == MethodAttributes.FamANDAssem))) { privateScope |= MethodAttributes.CheckAccessOnOverride; } this.func = new FunctionObject(this.name, formal_parameters, return_type, body, own_scope, obj2, base.context, privateScope, customAttributes, this.isMethod); if (this.declaringObject == null) { string str2 = this.name; if (this.ifaceId != null) { str2 = ifaceId.ToString() + "." + str2; } JSVariableField field = (JSVariableField) ((ActivationObject) obj2).name_table[str2]; if ((field != null) && ((!(field is JSMemberField) || !(((JSMemberField) field).value is FunctionObject)) || this.func.isExpandoMethod)) { if (name != this.name) { field.originalContext.HandleError(JSError.ClashWithProperty); } else { id.context.HandleError(JSError.DuplicateName, this.func.isExpandoMethod); if (field.value is FunctionObject) { ((FunctionObject) field.value).suppressIL = true; } } } if (this.isMethod) { if ((!(field is JSMemberField) || !(((JSMemberField) field).value is FunctionObject)) || (name != this.name)) { this.field = ((ActivationObject) obj2).AddNewField(str2, this.func, attributes | FieldAttributes.Literal); if (name == this.name) { this.field.type = new TypeExpression(new ConstantWrapper(Typeob.FunctionWrapper, base.context)); } } else { this.field = ((JSMemberField) field).AddOverload(this.func, attributes | FieldAttributes.Literal); } } else if (obj2 is FunctionScope) { if (this.inFastScope) { attributes |= FieldAttributes.Literal; } this.field = ((FunctionScope) obj2).AddNewField(this.name, attributes, this.func); if (this.field is JSLocalField) { JSLocalField field2 = (JSLocalField) this.field; if (this.inFastScope) { field2.type = new TypeExpression(new ConstantWrapper(Typeob.ScriptFunction, base.context)); field2.attributeFlags |= FieldAttributes.Literal; } field2.debugOn = base.context.document.debugOn; field2.isDefined = true; } } else if (this.inFastScope) { this.field = ((ActivationObject) obj2).AddNewField(this.name, this.func, attributes | FieldAttributes.Literal); this.field.type = new TypeExpression(new ConstantWrapper(Typeob.ScriptFunction, base.context)); } else { this.field = ((ActivationObject) obj2).AddNewField(this.name, this.func, attributes | FieldAttributes.Static); } this.field.originalContext = context; if (name != this.name) { string str3 = name; if (this.ifaceId != null) { str3 = ifaceId.ToString() + "." + name; } FieldInfo info = (FieldInfo) ((ClassScope) obj2).name_table[str3]; if (info != null) { if (info.IsLiteral) { object obj3 = ((JSVariableField) info).value; if (obj3 is JSProperty) { this.enclosingProperty = (JSProperty) obj3; } } if (this.enclosingProperty == null) { id.context.HandleError(JSError.DuplicateName, true); } } if (this.enclosingProperty == null) { this.enclosingProperty = new JSProperty(name); ((JSMemberField) ((ActivationObject) obj2).AddNewField(str3, this.enclosingProperty, attributes | FieldAttributes.Literal)).originalContext = base.context; } else if ((isGetter && (this.enclosingProperty.getter != null)) || (isSetter && (this.enclosingProperty.setter != null))) { id.context.HandleError(JSError.DuplicateName, true); } if (isGetter) { this.enclosingProperty.getter = new JSFieldMethod(this.field, obj2); } else { this.enclosingProperty.setter = new JSFieldMethod(this.field, obj2); } } } } else { this.inFastScope = false; this.func = new FunctionObject(this.name, formal_parameters, return_type, body, own_scope, obj2, base.context, MethodAttributes.Public, null, false); this.field = ((StackFrame) obj2).AddNewField(this.name, new Closure(this.func), attributes | FieldAttributes.Static); } }
private AST ParseFunction(FieldAttributes visibilitySpec, bool inExpression, Context fncCtx, bool isMethod, bool isAbstract, bool isFinal, bool isInterface, CustomAttributeList customAttributes, Call function) { AST ast2; if (this.demandFullTrustOnFunctionCreation) { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); } IdentifierLiteral id = null; AST rootObject = null; ArrayList parameters = null; TypeExpression expression = null; Block body = null; bool isGetter = false; bool isSetter = false; if (function == null) { this.GetNextToken(); if (isMethod) { if (JSToken.Get == this.currentToken.token) { isGetter = true; this.GetNextToken(); } else if (JSToken.Set == this.currentToken.token) { isSetter = true; this.GetNextToken(); } } if (JSToken.Identifier == this.currentToken.token) { id = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); this.GetNextToken(); if (JSToken.AccessField == this.currentToken.token) { if (isInterface) { this.ReportError(JSError.SyntaxError, true); } this.GetNextToken(); if (JSToken.Identifier == this.currentToken.token) { rootObject = new Lookup(id.context); id = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); this.GetNextToken(); while (JSToken.AccessField == this.currentToken.token) { this.GetNextToken(); if (JSToken.Identifier == this.currentToken.token) { rootObject = new Member(rootObject.context.CombineWith(this.currentToken), rootObject, new ConstantWrapper(id.ToString(), id.context)); id = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); this.GetNextToken(); } else { this.ReportError(JSError.NoIdentifier, true); } } } else { this.ReportError(JSError.NoIdentifier, true); } } } else { string identifier = JSKeyword.CanBeIdentifier(this.currentToken.token); if (identifier != null) { this.ForceReportInfo(JSError.KeywordUsedAsIdentifier, isMethod); id = new IdentifierLiteral(identifier, this.currentToken.Clone()); this.GetNextToken(); } else { if (!inExpression) { identifier = this.currentToken.GetCode(); this.ReportError(JSError.NoIdentifier, true); this.GetNextToken(); } else { identifier = ""; } id = new IdentifierLiteral(identifier, this.CurrentPositionContext()); } } } else { id = function.GetName(); } ArrayList blockType = this.blockType; this.blockType = new ArrayList(0x10); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(0x10); FunctionScope item = new FunctionScope(this.Globals.ScopeStack.Peek(), isMethod); this.Globals.ScopeStack.Push(item); try { parameters = new ArrayList(); Context context = null; if (function == null) { if (JSToken.LeftParen != this.currentToken.token) { this.ReportError(JSError.NoLeftParen); } this.GetNextToken(); while (JSToken.RightParen != this.currentToken.token) { if (context != null) { this.ReportError(JSError.ParamListNotLast, context, true); context = null; } string str2 = null; TypeExpression type = null; this.noSkipTokenSet.Add(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); try { try { if (JSToken.ParamArray == this.currentToken.token) { context = this.currentToken.Clone(); this.GetNextToken(); } if ((JSToken.Identifier != this.currentToken.token) && ((str2 = JSKeyword.CanBeIdentifier(this.currentToken.token)) == null)) { if (JSToken.LeftCurly == this.currentToken.token) { this.ReportError(JSError.NoRightParen); break; } if (JSToken.Comma == this.currentToken.token) { this.ReportError(JSError.SyntaxError, true); } else { this.ReportError(JSError.SyntaxError, true); this.SkipTokensAndThrow(); } } else { if (str2 == null) { str2 = this.scanner.GetIdentifier(); } else { this.ForceReportInfo(JSError.KeywordUsedAsIdentifier); } Context context2 = this.currentToken.Clone(); this.GetNextToken(); if (JSToken.Colon == this.currentToken.token) { type = this.ParseTypeExpression(); if (type != null) { context2.UpdateWith(type.context); } } CustomAttributeList list3 = null; if (context != null) { list3 = new CustomAttributeList(context); list3.Append(new Microsoft.JScript.CustomAttribute(context, new Lookup("...", context), new ASTList(null))); } parameters.Add(new ParameterDeclaration(context2, str2, type, list3)); } if (JSToken.RightParen == this.currentToken.token) { break; } if (JSToken.Comma != this.currentToken.token) { if (JSToken.LeftCurly == this.currentToken.token) { this.ReportError(JSError.NoRightParen); break; } if ((JSToken.Identifier == this.currentToken.token) && (type == null)) { this.ReportError(JSError.NoCommaOrTypeDefinitionError); } else { this.ReportError(JSError.NoComma); } } this.GetNextToken(); } catch (RecoveryTokenException exception) { if (this.IndexOfToken(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet, exception) == -1) { throw exception; } } continue; } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); } } fncCtx.UpdateWith(this.currentToken); if (isGetter && (parameters.Count != 0)) { this.ReportError(JSError.BadPropertyDeclaration, true); isGetter = false; } else if (isSetter && (parameters.Count != 1)) { this.ReportError(JSError.BadPropertyDeclaration, true); isSetter = false; } this.GetNextToken(); if (JSToken.Colon == this.currentToken.token) { if (isSetter) { this.ReportError(JSError.SyntaxError); } this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); try { expression = this.ParseTypeExpression(); } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_StartBlockNoSkipTokenSet, exception2) == -1) { exception2._partiallyComputedNode = null; throw exception2; } if (exception2._partiallyComputedNode != null) { expression = (TypeExpression) exception2._partiallyComputedNode; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); } if (isSetter) { expression = null; } } } else { function.GetParameters(parameters); } if ((JSToken.LeftCurly != this.currentToken.token) && (isAbstract || (isMethod && this.GuessIfAbstract()))) { if (!isAbstract) { isAbstract = true; this.ReportError(JSError.ShouldBeAbstract, fncCtx, true); } body = new Block(this.currentToken.Clone()); } else { if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly, true); } else if (isAbstract) { this.ReportError(JSError.AbstractWithBody, fncCtx, true); } this.blockType.Add(BlockType.Block); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try { body = new Block(this.currentToken.Clone()); this.GetNextToken(); while (JSToken.RightCurly != this.currentToken.token) { try { body.Append(this.ParseStatement()); continue; } catch (RecoveryTokenException exception3) { if (exception3._partiallyComputedNode != null) { body.Append(exception3._partiallyComputedNode); } if (this.IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exception3) == -1) { throw exception3; } continue; } } body.context.UpdateWith(this.currentToken); fncCtx.UpdateWith(this.currentToken); } catch (RecoveryTokenException exception4) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception4) == -1) { this.Globals.ScopeStack.Pop(); try { ParameterDeclaration[] declarationArray = new ParameterDeclaration[parameters.Count]; parameters.CopyTo(declarationArray); if (inExpression) { exception4._partiallyComputedNode = new FunctionExpression(fncCtx, id, declarationArray, expression, body, item, visibilitySpec); } else { exception4._partiallyComputedNode = new FunctionDeclaration(fncCtx, rootObject, id, declarationArray, expression, body, item, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); } if (customAttributes != null) { customAttributes.SetTarget(exception4._partiallyComputedNode); } } finally { this.Globals.ScopeStack.Push(item); } throw exception4; } } finally { this.blockType.RemoveAt(this.blockType.Count - 1); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } this.GetNextToken(); } } finally { this.blockType = blockType; this.labelTable = labelTable; this.Globals.ScopeStack.Pop(); } ParameterDeclaration[] array = new ParameterDeclaration[parameters.Count]; parameters.CopyTo(array); if (inExpression) { ast2 = new FunctionExpression(fncCtx, id, array, expression, body, item, visibilitySpec); } else { ast2 = new FunctionDeclaration(fncCtx, rootObject, id, array, expression, body, item, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); } if (customAttributes != null) { customAttributes.SetTarget(ast2); } return ast2; }