internal FunctionObject(Type t, string name, string method_name, string[] formal_parameters, JSLocalField[] fields, bool must_save_stack_locals, bool hasArgumentsObject, string text, VsaEngine engine) : base(engine.Globals.globalObject.originalFunction.originalPrototype, name, formal_parameters.Length) { base.engine = engine; this.formal_parameters = formal_parameters; this.argumentsSlotNumber = 0; this.body = null; this.method = TypeReflector.GetTypeReflectorFor(Globals.TypeRefs.ToReferenceContext(t)).GetMethod(method_name, BindingFlags.Public | BindingFlags.Static); this.parameterInfos = this.method.GetParameters(); if (!Microsoft.JScript.CustomAttribute.IsDefined(this.method, typeof(JSFunctionAttribute), false)) { this.isMethod = true; } else { JSFunctionAttributeEnum attributeValue = ((JSFunctionAttribute) Microsoft.JScript.CustomAttribute.GetCustomAttributes(this.method, typeof(JSFunctionAttribute), false)[0]).attributeValue; this.isExpandoMethod = (attributeValue & JSFunctionAttributeEnum.IsExpandoMethod) != JSFunctionAttributeEnum.None; } this.funcContext = null; this.own_scope = null; this.fields = fields; this.must_save_stack_locals = must_save_stack_locals; this.hasArgumentsObject = hasArgumentsObject; this.text = text; this.attributes = MethodAttributes.Public; this.globals = engine.Globals; this.superConstructor = null; this.superConstructorCall = null; this.enclosing_scope = this.globals.ScopeStack.Peek(); base.noExpando = false; this.clsCompliance = CLSComplianceSpec.NotAttributed; }
internal StaticInitializer(Context context, Block body, FunctionScope own_scope) : base(context) { this.func = new FunctionObject(null, new ParameterDeclaration[0], null, body, own_scope, Globals.ScopeStack.Peek(), context, MethodAttributes.Private|MethodAttributes.Static); this.func.isMethod = true; this.func.hasArgumentsObject = false; this.completion = new Completion(); }
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 Call(Context context, AST func, ASTList args, bool inBrackets) : base(context) { this.func = func; this.args = (args == null) ? new ASTList(context) : args; this.argValues = null; this.outParameterCount = 0; int num = 0; int count = this.args.count; while (num < count) { if (this.args[num] is AddressOf) { this.outParameterCount++; } num++; } this.isConstructor = false; this.inBrackets = inBrackets; this.enclosingFunctionScope = null; this.alreadyPartiallyEvaluated = false; this.isAssignmentToDefaultIndexedProperty = false; ScriptObject parent = base.Globals.ScopeStack.Peek(); while (!(parent is FunctionScope)) { parent = parent.GetParent(); if (parent == null) { return; } } this.enclosingFunctionScope = (FunctionScope) parent; }
internal Eval(Context context, AST operand, AST unsafeOption) : base(context) { this.operand = operand; this.unsafeOption = unsafeOption; ScriptObject obj2 = base.Globals.ScopeStack.Peek(); ((IActivationObject) obj2).GetGlobalScope().evilScript = true; if (obj2 is ActivationObject) { ((ActivationObject) obj2).isKnownAtCompileTime = base.Engine.doFast; } if (obj2 is FunctionScope) { this.enclosingFunctionScope = (FunctionScope) obj2; this.enclosingFunctionScope.mustSaveStackLocals = true; for (ScriptObject obj3 = this.enclosingFunctionScope.GetParent(); obj3 != null; obj3 = obj3.GetParent()) { FunctionScope scope = obj3 as FunctionScope; if (scope != null) { scope.mustSaveStackLocals = true; scope.closuresMightEscape = true; } } } else { this.enclosingFunctionScope = null; } }
private void AllocateFunctionScope(){ if (this.nestedFunctionScope != null) return; this.nestedFunctionScope = new FunctionScope(this.parent); if (this.fields != null) for (int i = 0, n = this.fields.Length; i < n; i++) this.nestedFunctionScope.AddOuterScopeField(this.fields[i].Name, this.fields[i]); }
internal With(Context context, AST obj, AST block) : base(context) { this.obj = obj; this.block = block; this.completion = new Completion(); ScriptObject scope = Globals.ScopeStack.Peek(); if (scope is FunctionScope) this.enclosing_function = (FunctionScope)scope; else this.enclosing_function = null; }
internal JSLocalField(String name, FunctionScope scope, int slotNumber, Object value) : base(name, scope, FieldAttributes.Static|FieldAttributes.Public) { this.slotNumber = slotNumber; this.inferred_type = null; this.dependents = null; this.value = value; this.debugOn = false; this.outerField = null; this.isDefined = false; this.isUsedBeforeDefinition = false; }
internal StackFrame(ScriptObject parent, JSLocalField[] fields, Object[] local_vars, Object thisObject) : base(parent) { this.caller_arguments = null; this.fields = fields; this.localVars = local_vars; this.nestedFunctionScope = null; this.thisObject = thisObject; if (parent is StackFrame) this.closureInstance = ((StackFrame)parent).closureInstance; else if (parent is JSObject) this.closureInstance = parent; else this.closureInstance = null; }
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 With(Context context, AST obj, AST block) : base(context) { this.obj = obj; this.block = block; this.completion = new Completion(); ScriptObject obj2 = base.Globals.ScopeStack.Peek(); if (obj2 is FunctionScope) { this.enclosing_function = (FunctionScope) obj2; } else { this.enclosing_function = null; } }
private void AllocateFunctionScope() { if (this.nestedFunctionScope == null) { this.nestedFunctionScope = new FunctionScope(base.parent); if (this.fields != null) { int index = 0; int length = this.fields.Length; while (index < length) { this.nestedFunctionScope.AddOuterScopeField(this.fields[index].Name, this.fields[index]); index++; } } } }
internal Return(Context context, AST operand, bool leavesFinally) : base(context) { this.completion = new Completion(); this.completion.Return = true; this.operand = operand; ScriptObject scope = Globals.ScopeStack.Peek(); while (!(scope is FunctionScope)){ scope = scope.GetParent(); if (scope == null){ this.context.HandleError(JSError.BadReturn); scope = new FunctionScope(null); } } this.enclosingFunctionScope = ((FunctionScope)scope); if (this.operand != null && this.enclosingFunctionScope.returnVar == null) this.enclosingFunctionScope.AddReturnValueField(); this.leavesFinally = leavesFinally; }
// Perform a call on this object. internal override Object Call (VsaEngine engine, Object thisob, Object[] args) { // Create a new scope object and initialize the parameters. ScriptObject scope; if(thisob is JSObject) { scope = new FunctionScope ((JSObject)thisob, defn.fparams, thisob, args); } else { scope = new FunctionScope (declaringScope, defn.fparams, thisob, args); } // Push the scope onto the stack. engine.PushScriptObjectChecked(scope); // Call the function and pop the scope afterwards. Object result = Empty.Value; try { if(defn.body != null) { defn.body.Eval(engine); } } catch(ReturnJumpOut r) { return r.value; } finally { engine.PopScriptObject(); } // Return the function result to the caller. return result; }
internal Call(Context context, AST func, ASTList args, bool inBrackets) : base(context) { this.func = func; this.args = args == null ? new ASTList(context) : args; this.argValues = null; this.outParameterCount = 0; for (int i = 0, n = this.args.count; i < n; i++) if (this.args[i] is AddressOf) this.outParameterCount++; this.isConstructor = false; this.inBrackets = inBrackets; this.enclosingFunctionScope = null; this.alreadyPartiallyEvaluated = false; this.isAssignmentToDefaultIndexedProperty = false; ScriptObject scope = Globals.ScopeStack.Peek(); while (!(scope is FunctionScope)){ scope = scope.GetParent(); if (scope == null) return; } this.enclosingFunctionScope = (FunctionScope)scope; }
internal Return(Context context, AST operand, bool leavesFinally) : base(context) { this.completion = new Completion(); this.completion.Return = true; this.operand = operand; ScriptObject parent = base.Globals.ScopeStack.Peek(); while (!(parent is FunctionScope)) { parent = parent.GetParent(); if (parent == null) { base.context.HandleError(JSError.BadReturn); parent = new FunctionScope(null); } } this.enclosingFunctionScope = (FunctionScope) parent; if ((this.operand != null) && (this.enclosingFunctionScope.returnVar == null)) { this.enclosingFunctionScope.AddReturnValueField(); } this.leavesFinally = leavesFinally; }
internal Eval(Context context, AST operand) : base(context) { this.operand = operand; ScriptObject enclosingScope = Globals.ScopeStack.Peek(); ((IActivationObject)enclosingScope).GetGlobalScope().evilScript = true; if (enclosingScope is ActivationObject) ((ActivationObject)enclosingScope).isKnownAtCompileTime = this.Engine.doFast; if (enclosingScope is FunctionScope){ this.enclosingFunctionScope = (FunctionScope)enclosingScope; this.enclosingFunctionScope.mustSaveStackLocals = true; ScriptObject scope = (ScriptObject)this.enclosingFunctionScope.GetParent(); while (scope != null){ FunctionScope fscope = scope as FunctionScope; if (fscope != null){ fscope.mustSaveStackLocals = true; fscope.closuresMightEscape = true; } scope = (ScriptObject)scope.GetParent(); } }else this.enclosingFunctionScope = null; }
private AST ParseAttributes(AST statement, bool unambiguousContext, bool isInsideClass, out bool parsedOK) { JSToken none; bool flag; bool flag2; AST ast = statement; ArrayList list = new ArrayList(); ArrayList list2 = new ArrayList(); ArrayList list3 = new ArrayList(); AST ast2 = null; ArrayList list4 = new ArrayList(); Context context = null; Context context2 = null; Context context3 = null; int num = 0; if (unambiguousContext) { num = 2; } FieldAttributes privateScope = FieldAttributes.PrivateScope; FieldAttributes family = FieldAttributes.PrivateScope; Context enumCtx = null; if (statement != null) { ast2 = statement; list4.Add(statement); list.Add(this.CurrentPositionContext()); enumCtx = statement.context.Clone(); num = 1; } else { enumCtx = this.currentToken.Clone(); } parsedOK = true; Label_0078: none = JSToken.None; switch (this.currentToken.token) { case JSToken.Boolean: case JSToken.Byte: case JSToken.Char: case JSToken.Double: case JSToken.Float: case JSToken.Int: case JSToken.Long: case JSToken.Short: case JSToken.Void: parsedOK = false; ast2 = new Lookup(this.currentToken); none = JSToken.None; list4.Add(ast2); this.GetNextToken(); goto Label_0A12; case JSToken.Enum: { int num8 = 0; int num9 = list3.Count; while (num8 < num9) { this.ReportError((JSError) list3[num8], (Context) list3[num8 + 1], true); num8 += 2; } enumCtx.UpdateWith(this.currentToken); if (context != null) { this.ReportError(JSError.IllegalVisibility, context, true); } if (context3 != null) { this.ReportError(JSError.IllegalVisibility, context3, true); } if (context2 != null) { this.ReportError(JSError.IllegalVisibility, context2, true); } return this.ParseEnum(privateScope, enumCtx, this.FromASTListToCustomAttributeList(list4)); } case JSToken.Interface: if (context != null) { this.ReportError(JSError.IllegalVisibility, context, true); context = null; } if (context3 != null) { this.ReportError(JSError.IllegalVisibility, context3, true); context3 = null; } if (context2 != null) { this.ReportError(JSError.IllegalVisibility, context2, true); context2 = null; } break; case JSToken.Internal: case JSToken.Abstract: case JSToken.Public: case JSToken.Static: case JSToken.Private: case JSToken.Protected: case JSToken.Final: none = this.currentToken.token; goto Label_042A; case JSToken.Var: case JSToken.Const: { int num2 = 0; int num3 = list3.Count; while (num2 < num3) { this.ReportError((JSError) list3[num2], (Context) list3[num2 + 1], true); num2 += 2; } if (context != null) { this.ReportError(JSError.IllegalVisibility, context, true); } if (context3 != null) { this.ReportError(JSError.IllegalVisibility, context3, true); } enumCtx.UpdateWith(this.currentToken); return this.ParseVariableStatement(privateScope, this.FromASTListToCustomAttributeList(list4), this.currentToken.token); } case JSToken.Class: break; case JSToken.Function: { int num4 = 0; int num5 = list3.Count; while (num4 < num5) { this.ReportError((JSError) list3[num4], (Context) list3[num4 + 1], true); num4 += 2; } enumCtx.UpdateWith(this.currentToken); if (context2 != null) { if (context != null) { context2.HandleError(JSError.AbstractCannotBeStatic); context2 = null; } else if (context3 != null) { context3.HandleError(JSError.StaticIsAlreadyFinal); context3 = null; } } if (context != null) { if (context3 != null) { context3.HandleError(JSError.FinalPrecludesAbstract); context3 = null; } if (family == FieldAttributes.Private) { context.HandleError(JSError.AbstractCannotBePrivate); family = FieldAttributes.Family; } } return this.ParseFunction(privateScope, false, enumCtx, isInsideClass, context != null, context3 != null, false, this.FromASTListToCustomAttributeList(list4)); } case JSToken.Identifier: goto Label_042A; default: goto Label_047E; } int num6 = 0; int count = list3.Count; while (num6 < count) { this.ReportError((JSError) list3[num6], (Context) list3[num6 + 1], true); num6 += 2; } enumCtx.UpdateWith(this.currentToken); if ((context3 != null) && (context != null)) { context3.HandleError(JSError.FinalPrecludesAbstract); } return this.ParseClass(privateScope, context2 != null, enumCtx, context != null, context3 != null, this.FromASTListToCustomAttributeList(list4)); Label_042A: flag2 = true; statement = this.ParseUnaryExpression(out flag, ref flag2, false, none == JSToken.None); ast2 = statement; if (none != JSToken.None) { if (statement is Lookup) { goto Label_07ED; } if (num != 2) { list2.Add(this.currentToken.Clone()); } } none = JSToken.None; if (flag2) { list4.Add(statement); goto Label_0A12; } Label_047E: parsedOK = false; if (num != 2) { if ((ast != statement) || (statement == null)) { statement = ast2; int num10 = 0; int num11 = list2.Count; while (num10 < num11) { this.ForceReportInfo((Context) list2[num10], JSError.KeywordUsedAsIdentifier); num10++; } int num12 = 0; int num13 = list.Count; while (num12 < num13) { if (!this.currentToken.Equals((Context) list[num12])) { this.ReportError(JSError.NoSemicolon, (Context) list[num12], true); } num12++; } } return statement; } if (list4.Count > 0) { AST ast3 = (AST) list4[list4.Count - 1]; if (ast3 is Lookup) { if ((JSToken.Semicolon == this.currentToken.token) || (JSToken.Colon == this.currentToken.token)) { this.ReportError(JSError.BadVariableDeclaration, ast3.context.Clone()); this.SkipTokensAndThrow(); } } else if ((ast3 is Call) && ((Call) ast3).CanBeFunctionDeclaration()) { if ((JSToken.Colon == this.currentToken.token) || (JSToken.LeftCurly == this.currentToken.token)) { this.ReportError(JSError.BadFunctionDeclaration, ast3.context.Clone(), true); if (JSToken.Colon == this.currentToken.token) { this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); try { this.SkipTokensAndThrow(); } catch (RecoveryTokenException) { } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); } } this.errorToken = null; if (JSToken.LeftCurly == this.currentToken.token) { FunctionScope item = new FunctionScope(this.Globals.ScopeStack.Peek(), isInsideClass); this.Globals.ScopeStack.Push(item); try { this.ParseBlock(); } finally { this.Globals.ScopeStack.Pop(); } this.SkipTokensAndThrow(); } } else { this.ReportError(JSError.SyntaxError, ast3.context.Clone()); } this.SkipTokensAndThrow(); } } if ((JSToken.LeftCurly == this.currentToken.token) && isInsideClass) { int num14 = 0; int num15 = list3.Count; while (num14 < num15) { this.ReportError((JSError) list3[num14], (Context) list3[num14 + 1]); num14 += 2; } if (context2 == null) { this.ReportError(JSError.StaticMissingInStaticInit, this.CurrentPositionContext()); } string name = ((ClassScope) this.Globals.ScopeStack.Peek()).name; bool flag3 = true; foreach (object obj2 in list4) { flag3 = false; if (((context2 == null) || !(obj2 is Lookup)) || ((obj2.ToString() != name) || (((Lookup) obj2).context.StartColumn <= context2.StartColumn))) { this.ReportError(JSError.SyntaxError, ((AST) obj2).context); } } if (flag3) { this.ReportError(JSError.NoIdentifier, this.CurrentPositionContext()); } this.errorToken = null; parsedOK = true; return this.ParseStaticInitializer(enumCtx); } this.ReportError(JSError.MissingConstructForAttributes, enumCtx.CombineWith(this.currentToken)); this.SkipTokensAndThrow(); Label_07ED: switch (none) { case JSToken.Internal: family = FieldAttributes.Assembly; break; case JSToken.Abstract: if (context == null) { context = statement.context.Clone(); } else { list3.Add(JSError.SyntaxError); list3.Add(statement.context.Clone()); } goto Label_0A12; case JSToken.Public: family = FieldAttributes.Public; break; case JSToken.Static: if (!isInsideClass) { list3.Add(JSError.NotInsideClass); list3.Add(statement.context.Clone()); break; } family = FieldAttributes.Static; if (context2 == null) { context2 = statement.context.Clone(); break; } list3.Add(JSError.SyntaxError); list3.Add(statement.context.Clone()); break; case JSToken.Private: if (!isInsideClass) { list3.Add(JSError.NotInsideClass); list3.Add(statement.context.Clone()); break; } family = FieldAttributes.Private; break; case JSToken.Protected: if (!isInsideClass) { list3.Add(JSError.NotInsideClass); list3.Add(statement.context.Clone()); break; } family = FieldAttributes.Family; break; case JSToken.Final: if (context3 == null) { context3 = statement.context.Clone(); } else { list3.Add(JSError.SyntaxError); list3.Add(statement.context.Clone()); } goto Label_0A12; } if (((privateScope & FieldAttributes.FieldAccessMask) == family) && (family != FieldAttributes.PrivateScope)) { list3.Add(JSError.DupVisibility); list3.Add(statement.context.Clone()); } else if (((privateScope & FieldAttributes.FieldAccessMask) > FieldAttributes.PrivateScope) && ((family & FieldAttributes.FieldAccessMask) > FieldAttributes.PrivateScope)) { if (((family == FieldAttributes.Family) && ((privateScope & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly)) || ((family == FieldAttributes.Assembly) && ((privateScope & FieldAttributes.FieldAccessMask) == FieldAttributes.Family))) { privateScope &= ~FieldAttributes.FieldAccessMask; privateScope |= FieldAttributes.FamORAssem; } else { list3.Add(JSError.IncompatibleVisibility); list3.Add(statement.context.Clone()); } } else { privateScope |= family; enumCtx.UpdateWith(statement.context); } Label_0A12: if (num != 2) { if (this.scanner.GotEndOfLine()) { num = 0; } else { num++; list.Add(this.currentToken.Clone()); } } goto Label_0078; }
private void TranslateToILToCopyLocalsFromNestedScope(ILGenerator il, FunctionScope nestedScope){ int offset = (this.attributes&MethodAttributes.Static) == MethodAttributes.Static ? 0 : 1; int n = this.fields.Length; for (int i = 0; i < n; i++){ JSLocalField field = nestedScope.GetOuterLocalField(this.fields[i].Name); if (field == null || field.outerField != this.fields[i]) continue; il.Emit(OpCodes.Dup); ConstantWrapper.TranslateToILInt(il, this.fields[i].slotNumber); il.Emit(OpCodes.Ldloc, (LocalBuilder)field.metaData); Convert.Emit(this.body, il, this.fields[i].FieldType, Typeob.Object); il.Emit(OpCodes.Stelem_Ref); } il.Emit(OpCodes.Pop); }
public override MemberInfo[] GetMember(String name, BindingFlags bindingAttr) { FieldInfo field = (FieldInfo)(this.name_table[name]); if (field != null) { return new MemberInfo[] { field } } ; bool nestedInInstanceMethod = false; ScriptObject parent = this.parent; //Treat locals of outer functions as if they were locals of this function while (parent is FunctionScope) { FunctionScope fscope = (FunctionScope)parent; nestedInInstanceMethod = fscope.isMethod && !fscope.isStatic; JSLocalField lfield = (JSLocalField)fscope.name_table[name]; if (lfield == null) { parent = parent.GetParent(); continue; } if (lfield.IsLiteral && !(lfield.value is FunctionObject)) { return new MemberInfo[] { lfield } } ; JSLocalField f = new JSLocalField(lfield.Name, this, this.field_table.Count, Missing.Value); f.outerField = lfield; f.debugOn = lfield.debugOn; if (!f.debugOn && this.owner.funcContext.document.debugOn && fscope.owner.funcContext.document.debugOn) { //Check to see it is off because outer field is a parameter f.debugOn = Array.IndexOf(fscope.owner.formal_parameters, lfield.Name) >= 0; } f.isDefined = lfield.isDefined; f.debuggerName = "outer" + "." + f.Name; if (lfield.IsLiteral) { f.attributeFlags |= FieldAttributes.Literal; f.value = lfield.value; } this.AddOuterScopeField(name, f); if (this.ProvidesOuterScopeLocals[parent] == null) { this.ProvidesOuterScopeLocals[parent] = parent; } ((FunctionScope)parent).mustSaveStackLocals = true; return(new MemberInfo[] { f }); } if (parent is ClassScope && nestedInInstanceMethod) { //return class members as if they were local to the function. It is more convenient to wrap up instance members //at this stage than it is to figure out later that a special case is involved. MemberInfo[] members = parent.GetMember(name, bindingAttr & ~BindingFlags.DeclaredOnly); int n = members.Length; bool giveBadNews = false; for (int i = 0; i < n; i++) { MemberInfo member = members[i]; switch (member.MemberType) { case MemberTypes.Field: field = (FieldInfo)member; if (field.IsLiteral) { JSMemberField mfield = field as JSMemberField; if (mfield != null && mfield.value is ClassScope && !((ClassScope)mfield.value).owner.IsStatic) { giveBadNews = true; } } if (!field.IsStatic && !field.IsLiteral) { members[i] = new JSClosureField(field); giveBadNews = true; } break; case MemberTypes.Method: MethodInfo meth = (MethodInfo)member; if (!meth.IsStatic) { members[i] = new JSClosureMethod(meth); giveBadNews = true; } break; case MemberTypes.Property: PropertyInfo prop = (PropertyInfo)member; MethodInfo getMeth = JSProperty.GetGetMethod(prop, (bindingAttr & BindingFlags.NonPublic) != 0); MethodInfo setMeth = JSProperty.GetSetMethod(prop, (bindingAttr & BindingFlags.NonPublic) != 0); bool nonStatic = false; if (getMeth != null && !getMeth.IsStatic) { nonStatic = true; getMeth = new JSClosureMethod(getMeth); } if (setMeth != null && !setMeth.IsStatic) { nonStatic = true; setMeth = new JSClosureMethod(setMeth); } if (nonStatic) { members[i] = new JSClosureProperty(prop, getMeth, setMeth); giveBadNews = true; } break; } } if (giveBadNews) { this.GiveOuterFunctionsTheBadNews(); //They have to create explicit stack frames } if (n > 0) { return(members); } } if ((bindingAttr & BindingFlags.DeclaredOnly) != 0) { return(new MemberInfo[0]); } return(parent.GetMember(name, bindingAttr)); }
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); } }
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(); } 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 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); } }
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 override AST PartiallyEvaluate() { this.condition = this.condition.PartiallyEvaluate(); if (this.condition is ConstantWrapper) { if (Convert.ToBoolean(this.condition.Evaluate()) == true) { this.operand2 = null; } else { this.operand1 = null; } this.condition = null; } ScriptObject current_scope = Globals.ScopeStack.Peek(); while (current_scope is WithObject) { current_scope = current_scope.GetParent(); } if (current_scope is FunctionScope) { FunctionScope scope = (FunctionScope)current_scope; BitArray before = scope.DefinedFlags; BitArray after1 = before; if (this.operand1 != null) { this.operand1 = this.operand1.PartiallyEvaluate(); after1 = scope.DefinedFlags; scope.DefinedFlags = before; } if (this.operand2 != null) { this.operand2 = this.operand2.PartiallyEvaluate(); BitArray after2 = scope.DefinedFlags; int n = after1.Length; int m = after2.Length; if (n < m) { after1.Length = m; } if (m < n) { after2.Length = n; } before = after1.And(after2); } scope.DefinedFlags = before; } else { if (this.operand1 != null) { this.operand1 = this.operand1.PartiallyEvaluate(); } if (this.operand2 != null) { this.operand2 = this.operand2.PartiallyEvaluate(); } } return(this); }
private void TranslateToILToCopyLocalsToNestedScope(ILGenerator il, FunctionScope nestedScope, JSLocalField[] notToBeRestored) { int length = this.fields.Length; for (int i = 0; i < length; i++) { JSLocalField outerLocalField = nestedScope.GetOuterLocalField(this.fields[i].Name); if (((outerLocalField != null) && (outerLocalField.outerField == this.fields[i])) && ((notToBeRestored == null) || !IsPresentIn(outerLocalField, notToBeRestored))) { il.Emit(OpCodes.Dup); ConstantWrapper.TranslateToILInt(il, this.fields[i].slotNumber); il.Emit(OpCodes.Ldelem_Ref); Microsoft.JScript.Convert.Emit(this.body, il, Typeob.Object, this.fields[i].FieldType); il.Emit(OpCodes.Stloc, (LocalBuilder) outerLocalField.metaData); } } il.Emit(OpCodes.Pop); }
private AST ParseStaticInitializer(Context initContext) { if (this.demandFullTrustOnFunctionCreation) { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); } Block body = null; FunctionScope item = new FunctionScope(this.Globals.ScopeStack.Peek()) { isStatic = true }; ArrayList blockType = this.blockType; this.blockType = new ArrayList(0x10); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(0x10); this.blockType.Add(BlockType.Block); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try { this.Globals.ScopeStack.Push(item); body = new Block(this.currentToken.Clone()); this.GetNextToken(); while (JSToken.RightCurly != this.currentToken.token) { try { body.Append(this.ParseStatement()); continue; } catch (RecoveryTokenException exception) { if (exception._partiallyComputedNode != null) { body.Append(exception._partiallyComputedNode); } if (this.IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exception) == -1) { throw exception; } continue; } } } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception2) == -1) { exception2._partiallyComputedNode = new StaticInitializer(initContext, body, item); throw exception2; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.blockType = blockType; this.labelTable = labelTable; this.Globals.ScopeStack.Pop(); } body.context.UpdateWith(this.currentToken); initContext.UpdateWith(this.currentToken); this.GetNextToken(); return new StaticInitializer(initContext, body, item); }
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); } }
//--------------------------------------------------------------------------------------- // ParseAttributes // // Package : // Attributes 'package' QualifiedIdentifier '{' ClassList '}' // AttributesStart 'package' QualifiedIdentifier '{' ClassList '}' // // Class : // Attributes 'class' Identifier ['extends' QualifiedIdentifier] '{' ClassBody '}' // AttributesStart 'class' Identifier ['extends' QualifiedIdentifier] '{' ClassBody '}' // // FunctionDeclaration : // Attributes 'function' Identifier '(' [FormalParameterList] ')' [':' TypeExpression] '{' FunctionBody '}' // AttributesStart 'function' Identifier '(' [FormalParameterList] ')' [':' TypeExpression] '{' FunctionBody '}' // // VariableStatement : // Attributes 'var' VariableDeclarationList // AttributesStart 'var' VariableDeclarationList // // Attributes : // AttributesStart AttributesNext | // Modifier [AttributeNext] // // AttributesStart : // QualifiedIdentifier /no LineTerminator here/ | // QualifiedIdentifier Arguments /no LineTerminator here/ // // AttributesNext : // QualifiedIdentifier [AttributesNext] | // QualifiedIdentifier Arguments [AttributesNext] | // Modifier [AttributesNext] // // Modifier : // 'private' | // 'public' | // 'protected' | // 'internal' | // 'package' | //This is going away // 'static' | // 'abstract' // // // Parse the list of attributes and the statement those attributes refer to. // It comes back with one of the following: package, class, function, variable declaration. // When in error it may return other AST constructs depending on the context. // The input is a possible attribute in the form of 'QualifiedIdentifier' or a sequence // 'QualifiedIdentifier Arguments' or null when the first attribute was a Modifier. // The whole sequence may be an error in the first place, so we want to keep // things such that we can always parse the supposed list of attributes as an ast list //--------------------------------------------------------------------------------------- AST ParseAttributes(AST statement, bool unambiguousContext, bool isInsideClass, out bool parsedOK){ // used later to verify whether anything at all has been processed AST inputAST = statement; // keep two list of errors. One holds the 'missing ;' errors that would result in the token // stream being parsed as a list of expressions, the other is the list of attributes errors // that would result from the token stream being parsed as a list of attributes. We need both because // we don't know until the end which is which ArrayList semicolonErrors = new ArrayList(); // keep track of the modifiers context in case they'll have to be parsed as identifiers, we give the warning out ArrayList modifiersAsIdentifier = new ArrayList(); // this list has two elements for each error, the first (even position - 0 based) is the error type // the second is the context ArrayList attributesErrors = new ArrayList(); // keep the last ast node parsed. Used if we have to "revert" to the expression list production. // We just return the last ast processed, after all is an error condition AST lastAST = null; // keep the list of attributes ArrayList attributes = new ArrayList(); // hold the context for the 'abstract' keyword and it is used as a flag for its presence Context abstractContext = null; // hold the context for the 'static' keyword and it is used as a flag for its presence Context staticContext = null; // hold the context for the 'final' keyword and it is used as a flag for its presence Context finalContext = null; // keep the number of consecutive token no separated by end of line. Once that number // reaches 2 the token stream is parsed *only* as a sequence of attributes int TokenCountNoEOL = 0; if (unambiguousContext) TokenCountNoEOL = 2; FieldAttributes visibilitySpec = (FieldAttributes)0, currVis = (FieldAttributes)0; Context statementContext = null; // null when coming from a visibility modifier if (statement != null){ lastAST = statement; attributes.Add(statement); semicolonErrors.Add(CurrentPositionContext()); statementContext = statement.context.Clone(); TokenCountNoEOL = 1; }else{ statementContext = this.currentToken.Clone(); } parsedOK = true; while (true){ JSToken attributeToken = JSToken.None; switch (this.currentToken.token){ case JSToken.Public: case JSToken.Static: case JSToken.Private: case JSToken.Protected: case JSToken.Abstract: case JSToken.Final: case JSToken.Internal: attributeToken = this.currentToken.token; goto case JSToken.Identifier; case JSToken.Var: case JSToken.Const: for (int i = 0, n = attributesErrors.Count; i < n; i += 2) ReportError((JSError)attributesErrors[i], (Context)attributesErrors[i + 1], true); if (abstractContext != null) ReportError(JSError.IllegalVisibility, abstractContext, true); if (finalContext != null) ReportError(JSError.IllegalVisibility, finalContext, true); statementContext.UpdateWith(this.currentToken); return ParseVariableStatement(visibilitySpec, FromASTListToCustomAttributeList(attributes), this.currentToken.token); case JSToken.Function: for (int i = 0, n = attributesErrors.Count; i < n; i += 2) ReportError((JSError)attributesErrors[i], (Context)attributesErrors[i + 1], true); statementContext.UpdateWith(this.currentToken); if (staticContext != null) if (abstractContext != null){ staticContext.HandleError(JSError.AbstractCannotBeStatic); staticContext = null; }else if (finalContext != null){ finalContext.HandleError(JSError.StaticIsAlreadyFinal); finalContext = null; } if (abstractContext != null){ if (finalContext != null){ finalContext.HandleError(JSError.FinalPrecludesAbstract); finalContext = null; } if (currVis == FieldAttributes.Private){ abstractContext.HandleError(JSError.AbstractCannotBePrivate); currVis = FieldAttributes.Family; } } return ParseFunction(visibilitySpec, false, statementContext, isInsideClass, abstractContext != null, finalContext != null, false, FromASTListToCustomAttributeList(attributes)); case JSToken.Interface: if (abstractContext != null){ ReportError(JSError.IllegalVisibility, abstractContext, true); abstractContext = null; } if (finalContext != null){ ReportError(JSError.IllegalVisibility, finalContext, true); finalContext = null; } if (staticContext != null){ ReportError(JSError.IllegalVisibility, staticContext, true); staticContext = null; } goto case JSToken.Class; case JSToken.Class: for (int i = 0, n = attributesErrors.Count; i < n; i += 2) ReportError((JSError)attributesErrors[i], (Context)attributesErrors[i + 1], true); statementContext.UpdateWith(this.currentToken); if (finalContext != null && abstractContext != null) finalContext.HandleError(JSError.FinalPrecludesAbstract); return ParseClass(visibilitySpec, staticContext != null, statementContext, abstractContext != null, finalContext != null, FromASTListToCustomAttributeList(attributes)); case JSToken.Enum: for (int i = 0, n = attributesErrors.Count; i < n; i += 2) ReportError((JSError)attributesErrors[i], (Context)attributesErrors[i + 1], true); statementContext.UpdateWith(this.currentToken); if (abstractContext != null) ReportError(JSError.IllegalVisibility, abstractContext, true); if (finalContext != null) ReportError(JSError.IllegalVisibility, finalContext, true); if (staticContext != null) ReportError(JSError.IllegalVisibility, staticContext, true); return ParseEnum(visibilitySpec, statementContext, FromASTListToCustomAttributeList(attributes)); case JSToken.Void: case JSToken.Boolean: case JSToken.Byte: case JSToken.Char: case JSToken.Double: case JSToken.Float: case JSToken.Int: case JSToken.Long: case JSToken.Short: { // The user has some sequence like "public int foo()", which // is probably a C-style function declaration. Save that away, // keep parsing and see if this ends in what looks like a function // or variable declaration. parsedOK = false; lastAST = new Lookup(this.currentToken); attributeToken = JSToken.None; attributes.Add(lastAST); GetNextToken(); goto continueLoop; } case JSToken.Identifier: { bool bAssign, canBeAttribute = true; statement = ParseUnaryExpression(out bAssign, ref canBeAttribute, false, attributeToken == JSToken.None); lastAST = statement; if (attributeToken != JSToken.None){ if (statement is Lookup) break; else{ if (TokenCountNoEOL != 2) modifiersAsIdentifier.Add(this.currentToken.Clone()); } } attributeToken = JSToken.None; if (canBeAttribute){ attributes.Add(statement); goto continueLoop; }else goto default; } // the following cases are somewhat interesting because they can be determined by a user missing // the keyword 'var' or 'function', as, for instance, when coming from C/C++/C# code default: parsedOK = false; if (TokenCountNoEOL != 2){ if (inputAST != statement || statement == null){ Debug.Assert(lastAST != null); // only return the last statement statement = lastAST; // output the semicolon errors for (int i = 0, n = modifiersAsIdentifier.Count; i < n; i++) ForceReportInfo((Context)modifiersAsIdentifier[i], JSError.KeywordUsedAsIdentifier); for (int i = 0, n = semicolonErrors.Count; i < n; i++) if (!this.currentToken.Equals((Context)semicolonErrors[i])) ReportError(JSError.NoSemicolon, (Context)semicolonErrors[i], true); } return statement; }else{ if (attributes.Count > 0){ // check for possible common mistakes AST ast = (AST)attributes[attributes.Count - 1]; if (ast is Lookup){ if (JSToken.Semicolon == this.currentToken.token || JSToken.Colon == this.currentToken.token){ ReportError(JSError.BadVariableDeclaration, ast.context.Clone()); SkipTokensAndThrow(); } }else if (ast is Call && ((Call)ast).CanBeFunctionDeclaration()){ if (JSToken.Colon == this.currentToken.token || JSToken.LeftCurly == this.currentToken.token){ ReportError(JSError.BadFunctionDeclaration, ast.context.Clone(), true); if (JSToken.Colon == this.currentToken.token){ this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); try{ SkipTokensAndThrow(); }catch(RecoveryTokenException){ }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); } } this.errorToken = null; if (JSToken.LeftCurly == this.currentToken.token){ FunctionScope fscope = new FunctionScope(Globals.ScopeStack.Peek(), isInsideClass); Globals.ScopeStack.Push(fscope); try{ ParseBlock(); }finally{ Globals.ScopeStack.Pop(); } SkipTokensAndThrow(); } } else ReportError(JSError.SyntaxError, ast.context.Clone()); SkipTokensAndThrow(); } } if (JSToken.LeftCurly == this.currentToken.token){ if (isInsideClass){ // parse it like a static initializer // flush all the possible attribute errors for (int i = 0, n = attributesErrors.Count; i < n; i += 2) ReportError((JSError)attributesErrors[i], (Context)attributesErrors[i + 1]); if (staticContext == null) ReportError(JSError.StaticMissingInStaticInit, CurrentPositionContext()); String className = ((ClassScope)Globals.ScopeStack.Peek()).name; bool reportNoIdentifier = true; foreach (Object attr in attributes){ reportNoIdentifier = false; if (staticContext != null && attr is Lookup && attr.ToString() == className && ((Lookup)attr).context.StartColumn > staticContext.StartColumn) continue; ReportError(JSError.SyntaxError, ((AST)attr).context); } if (reportNoIdentifier) ReportError(JSError.NoIdentifier, CurrentPositionContext()); this.errorToken = null; // we want to go to next token regardless of whether or not we had an error // return a static initializer parsedOK = true; return ParseStaticInitializer(statementContext); } } //mark them all as errors ReportError(JSError.MissingConstructForAttributes, statementContext.CombineWith(this.currentToken)); } SkipTokensAndThrow(); break; } switch (attributeToken){ case JSToken.Public: currVis = FieldAttributes.Public; break; case JSToken.Static: if (isInsideClass){ currVis = FieldAttributes.Static; if (staticContext != null){ attributesErrors.Add(JSError.SyntaxError); attributesErrors.Add(statement.context.Clone()); }else staticContext = statement.context.Clone(); }else{ attributesErrors.Add(JSError.NotInsideClass); attributesErrors.Add(statement.context.Clone()); } break; case JSToken.Private: if (isInsideClass) currVis = FieldAttributes.Private; else{ attributesErrors.Add(JSError.NotInsideClass); attributesErrors.Add(statement.context.Clone()); } break; case JSToken.Protected: if (isInsideClass){ currVis = FieldAttributes.Family; }else{ attributesErrors.Add(JSError.NotInsideClass); attributesErrors.Add(statement.context.Clone()); } break; case JSToken.Abstract: if (abstractContext != null){ attributesErrors.Add(JSError.SyntaxError); attributesErrors.Add(statement.context.Clone()); }else abstractContext = statement.context.Clone(); goto continueLoop; case JSToken.Final: if (finalContext != null){ attributesErrors.Add(JSError.SyntaxError); attributesErrors.Add(statement.context.Clone()); }else finalContext = statement.context.Clone(); goto continueLoop; case JSToken.Internal: currVis = FieldAttributes.Assembly; break; default: break; } // come here only after a visibility Modifer if ((visibilitySpec & FieldAttributes.FieldAccessMask) == currVis && currVis != (FieldAttributes)0){ attributesErrors.Add(JSError.DupVisibility); attributesErrors.Add(statement.context.Clone()); }else if ((visibilitySpec & FieldAttributes.FieldAccessMask) > (FieldAttributes)0 && (currVis & FieldAttributes.FieldAccessMask) > (FieldAttributes)0){ if ((currVis == FieldAttributes.Family && (visibilitySpec & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly) || (currVis == FieldAttributes.Assembly && (visibilitySpec & FieldAttributes.FieldAccessMask) == FieldAttributes.Family)){ visibilitySpec &= ~FieldAttributes.FieldAccessMask; visibilitySpec |= FieldAttributes.FamORAssem; }else{ attributesErrors.Add(JSError.IncompatibleVisibility); attributesErrors.Add(statement.context.Clone()); } }else{ visibilitySpec |= currVis; statementContext.UpdateWith(statement.context); } continueLoop: if (TokenCountNoEOL != 2){ if (this.scanner.GotEndOfLine()){ TokenCountNoEOL = 0; }else{ TokenCountNoEOL++; semicolonErrors.Add(this.currentToken.Clone()); } } } }
//--------------------------------------------------------------------------------------- // ParseStaticInitializer // // StaticInitializer : // '{' FunctionBody '}' //--------------------------------------------------------------------------------------- private AST ParseStaticInitializer(Context initContext){ Block body = null; FunctionScope scope = new FunctionScope(Globals.ScopeStack.Peek()); scope.isStatic = true; // 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); this.blockType.Add(BlockType.Block); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try{ Globals.ScopeStack.Push(scope); //Give declarations a place to go while building AST // 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; } } }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = new StaticInitializer(initContext, body, scope); throw exc; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.blockType = blockType; this.labelTable = labelTable; Globals.ScopeStack.Pop(); } body.context.UpdateWith(this.currentToken); initContext.UpdateWith(this.currentToken); GetNextToken(); return new StaticInitializer(initContext, body, scope); }
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; }
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; }