LoadScriptEngine() 공개 정적인 메소드

Pushes a reference to the script engine onto the stack.
public static LoadScriptEngine ( ILGenerator generator ) : void
generator ILGenerator The IL generator.
리턴 void
예제 #1
0
        /// <summary>
        /// Generates CIL for a call to eval().
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        private void GenerateEval(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // engine
            EmitHelpers.LoadScriptEngine(generator);

            // code
            if (this.OperandCount < 2)
            {
                // No arguments were supplied.
                generator.LoadNull();
            }
            else
            {
                // Take the first argument and convert it to a string.
                GenerateArgumentsArray(generator, optimizationInfo);
                generator.LoadInt32(0);
                generator.LoadArrayElement(typeof(object));
            }

            // scope
            EmitHelpers.LoadScope(generator);

            // thisObject
            EmitHelpers.LoadThis(generator);

            // strictMode
            generator.LoadBoolean(optimizationInfo.StrictMode);

            // Call Global.Eval(engine, code, scope, thisValue, strictMode)
            generator.Call(ReflectionHelpers.Global_Eval);
        }
예제 #2
0
 /// <summary>
 /// Emits a JavaScriptException.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 /// <param name="name"> The type of error to generate. </param>
 /// <param name="message"> The error message. </param>
 public static void EmitThrow(ILGenerator generator, string name, string message)
 {
     EmitHelpers.LoadScriptEngine(generator);
     generator.LoadString(name);
     generator.LoadString(message);
     generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
     generator.Throw();
 }
예제 #3
0
 /// <summary>
 /// Emits a JavaScriptException.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 /// <param name="name"> The type of error to generate. </param>
 /// <param name="message"> The error message. </param>
 /// <param name="path"> The path of the javascript source file that is currently executing. </param>
 /// <param name="function"> The name of the currently executing function. </param>
 /// <param name="line"> The line number of the statement that is currently executing. </param>
 public static void EmitThrow(ILGenerator generator, string name, string message, string path, string function, int line)
 {
     EmitHelpers.LoadScriptEngine(generator);
     generator.LoadString(name);
     generator.LoadString(message);
     generator.LoadInt32(line);
     generator.LoadStringOrNull(path);
     generator.LoadStringOrNull(function);
     generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
     generator.Throw();
 }
예제 #4
0
        /// <summary>
        /// Generates CIL for the in operator.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        private void GenerateIn(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Emit the left-hand side expression and convert it to a string.
            this.Left.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToString(generator, this.Left.ResultType);

            // Store the left-hand side expression in a temporary variable.
            var temp = generator.CreateTemporaryVariable(typeof(string));

            generator.StoreVariable(temp);

            // Emit the right-hand side expression.
            this.Right.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.Right.ResultType);

            // Check the right-hand side is a javascript object - if not, throw an exception.
            generator.Duplicate();
            generator.IsInstance(typeof(Library.ObjectInstance));
            var endOfTypeCheck = generator.CreateLabel();

            generator.BranchIfNotNull(endOfTypeCheck);

            // Throw an nicely formatted exception.
            var rightValue = generator.CreateTemporaryVariable(typeof(object));

            generator.StoreVariable(rightValue);
            EmitHelpers.LoadScriptEngine(generator);
            generator.LoadInt32((int)ErrorType.TypeError);
            generator.LoadString("The in operator expected an object, but found '{0}' instead");
            generator.LoadInt32(1);
            generator.NewArray(typeof(object));
            generator.Duplicate();
            generator.LoadInt32(0);
            generator.LoadVariable(rightValue);
            generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
            generator.StoreArrayElement(typeof(object));
            generator.Call(ReflectionHelpers.String_Format);
            generator.LoadInt32(optimizationInfo.SourceSpan.StartLine);
            generator.LoadStringOrNull(optimizationInfo.Source.Path);
            generator.LoadStringOrNull(optimizationInfo.FunctionName);
            generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
            generator.Throw();
            generator.DefineLabelPosition(endOfTypeCheck);
            generator.ReleaseTemporaryVariable(rightValue);

            // Load the left-hand side expression from the temporary variable.
            generator.LoadVariable(temp);

            // Call ObjectInstance.HasProperty(object)
            generator.Call(ReflectionHelpers.ObjectInstance_HasProperty);

            // Allow the temporary variable to be reused.
            generator.ReleaseTemporaryVariable(temp);
        }
예제 #5
0
        /// <summary>
        /// Pops the value on the stack, converts it to a javascript object, then pushes the result
        /// onto the stack.
        /// </summary>
        /// <param name="generator"> The IL generator. </param>
        /// <param name="fromType"> The type to convert from. </param>
        /// <param name="path"> The path of the javascript source file that is currently executing. </param>
        /// <param name="function"> The name of the currently executing function. </param>
        /// <param name="line"> The line number of the statement that is currently executing. </param>
        public static void ToObject(ILGenerator generator, PrimitiveType fromType, string path, string function, int line)
        {
            // Check that a conversion is actually necessary.
            if (fromType == PrimitiveType.Object)
            {
                generator.ReinterpretCast(typeof(ObjectInstance));
                return;
            }

            switch (fromType)
            {
            case PrimitiveType.Undefined:
                // Converting from undefined always throws an exception.
                EmitHelpers.EmitThrow(generator, ErrorType.TypeError, "Undefined cannot be converted to an object", path, function, line);
                generator.ReinterpretCast(typeof(ObjectInstance));
                break;

            case PrimitiveType.Null:
                // Converting from null always throws an exception.
                EmitHelpers.EmitThrow(generator, ErrorType.TypeError, "Null cannot be converted to an object", path, function, line);
                generator.ReinterpretCast(typeof(ObjectInstance));
                break;

            case PrimitiveType.Bool:
            case PrimitiveType.Int32:
            case PrimitiveType.UInt32:
            case PrimitiveType.Number:
            case PrimitiveType.String:
            case PrimitiveType.ConcatenatedString:
            case PrimitiveType.Any:
                // Otherwise, fall back to calling TypeConverter.ToObject()
                ToAny(generator, fromType);
                var temp = generator.CreateTemporaryVariable(typeof(object));
                generator.StoreVariable(temp);
                EmitHelpers.LoadScriptEngine(generator);
                generator.LoadVariable(temp);
                generator.ReleaseTemporaryVariable(temp);
                generator.LoadInt32(line);
                generator.LoadStringOrNull(path);
                generator.LoadStringOrNull(function);
                generator.Call(ReflectionHelpers.TypeConverter_ToObject);
                break;

            default:
                throw new NotImplementedException(string.Format("Unsupported primitive type: {0}", fromType));
            }
        }
예제 #6
0
        /// <summary>
        /// Generates code that creates a new scope.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        internal override void GenerateScopeCreation(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Create a new runtime object scope.
            EmitHelpers.LoadScope(generator);  // parent scope
            if (this.ScopeObjectExpression == null)
            {
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Global);
            }
            else
            {
                this.ScopeObjectExpression.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToObject(generator, this.ScopeObjectExpression.ResultType, optimizationInfo);
            }
            generator.LoadBoolean(this.ProvidesImplicitThisValue);
            generator.LoadBoolean(this.CanDeclareVariables);
            generator.Call(ReflectionHelpers.ObjectScope_CreateRuntimeScope);

            // Save the new scope.
            EmitHelpers.StoreScope(generator);
        }
예제 #7
0
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Operands for ArrayConstructor.New() are: an ArrayConstructor instance (ArrayConstructor), an array (object[])
            // ArrayConstructor
            EmitHelpers.LoadScriptEngine(generator);
            generator.Call(ReflectionHelpers.ScriptEngine_Array);

            // object[]
            generator.LoadInt32(Items.Count);
            generator.NewArray(typeof(object));
            for (int i = 0; i < Items.Count; i++)
            {
                // Operands for StoreArrayElement() are: an array (object[]), index (int), value (object).
                // Array
                generator.Duplicate();

                // Index
                generator.LoadInt32(i);

                // Value
                var elementExpression = Items[i];
                if (elementExpression == null)
                {
                    generator.LoadNull();
                }
                else
                {
                    elementExpression.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToAny(generator, elementExpression.ResultType);
                }

                // Store the element value.
                generator.StoreArrayElement(typeof(object));
            }

            // ArrayConstructor.New(object[])
            generator.Call(ReflectionHelpers.Array_New);
        }
예제 #8
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Generate code for the start of the statement.
            var statementLocals = new StatementLocals()
            {
                NonDefaultBreakStatementBehavior = true, NonDefaultSourceSpanBehavior = true
            };

            GenerateStartOfStatement(generator, optimizationInfo, statementLocals);

            // Construct a loop expression.
            // var iterator = TypeUtilities.GetIterator(obj);
            // while (true) {
            //   continue-target:
            //   if (enumerator.MoveNext() == false)
            //     goto break-target;
            //   lhs = enumerator.Current;
            //
            //   <body statements>
            // }
            // break-target:

            // Call: ObjectInstance GetIterator(ScriptEngine engine, ObjectInstance iterable)
            // Then call: IEnumerable<object> Iterate(ScriptEngine engine, ObjectInstance iterator)
            optimizationInfo.MarkSequencePoint(generator, this.TargetObjectSourceSpan);
            EmitHelpers.LoadScriptEngine(generator);
            this.TargetObject.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.TargetObject.ResultType);
            generator.Call(ReflectionHelpers.TypeUtilities_ForOf);

            // Call IEnumerable<object>.GetEnumerator()
            generator.Call(ReflectionHelpers.IEnumerable_Object_GetEnumerator);

            // Store the enumerator in a temporary variable.
            var enumerator = generator.CreateTemporaryVariable(typeof(IEnumerator <object>));

            generator.StoreVariable(enumerator);

            var breakTarget    = generator.CreateLabel();
            var continueTarget = generator.DefineLabelPosition();

            // Emit debugging information.
            if (optimizationInfo.DebugDocument != null)
            {
                generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.VariableSourceSpan);
            }

            //   if (enumerator.MoveNext() == false)
            //     goto break-target;
            generator.LoadVariable(enumerator);
            generator.Call(ReflectionHelpers.IEnumerator_MoveNext);
            generator.BranchIfFalse(breakTarget);

            // lhs = enumerator.Current;
            this.Variable.GenerateReference(generator, optimizationInfo);
            generator.LoadVariable(enumerator);
            generator.Call(ReflectionHelpers.IEnumerator_Object_Current);
            this.Variable.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);

            // Emit the body statement(s).
            optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget, continueTarget, labelledOnly: false);
            this.Body.GenerateCode(generator, optimizationInfo);
            optimizationInfo.PopBreakOrContinueInfo();

            generator.Branch(continueTarget);
            generator.DefineLabelPosition(breakTarget);

            // Generate code for the end of the statement.
            GenerateEndOfStatement(generator, optimizationInfo, statementLocals);
        }
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Literals cannot have side-effects so if a return value is not expected then generate
            // nothing.
            //if (optimizationInfo.SuppressReturnValue == true)
            //    return;

            if (this.Value is int)
            {
                generator.LoadInt32((int)this.Value);
            }
            else if (this.Value is double)
            {
                generator.LoadDouble((double)this.Value);
            }
            else if (this.Value is string)
            {
                generator.LoadString((string)this.Value);
            }
            else if (this.Value is bool)
            {
                generator.LoadBoolean((bool)this.Value);
            }
            else if (this.Value is RegularExpressionLiteral)
            {
                // RegExp
                var sharedRegExpVariable = optimizationInfo.GetRegExpVariable(generator, (RegularExpressionLiteral)this.Value);
                var label1 = generator.CreateLabel();
                var label2 = generator.CreateLabel();

                // if (sharedRegExp == null) {
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.BranchIfNotEqual(label1);

                // sharedRegExp = Global.RegExp.Construct(source, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Pattern);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Flags);
                generator.Call(ReflectionHelpers.RegExp_Construct);
                generator.Duplicate();
                generator.StoreVariable(sharedRegExpVariable);

                // } else {
                generator.Branch(label2);
                generator.DefineLabelPosition(label1);

                // Global.RegExp.Construct(sharedRegExp, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.Call(ReflectionHelpers.RegExp_Construct);

                // }
                generator.DefineLabelPosition(label2);
            }
            else if (this.Value == Null.Value)
            {
                // Null.
                EmitHelpers.EmitNull(generator);
            }
            else if (this.Value == Undefined.Value)
            {
                // Undefined.
                EmitHelpers.EmitUndefined(generator);
            }
            else if (this.Value is List <Expression> )
            {
                // Construct an array literal.
                var arrayLiteral = (List <Expression>) this.Value;

                // Operands for ArrayConstructor.New() are: an ArrayConstructor instance (ArrayConstructor), an array (object[])
                // ArrayConstructor
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Array);

                // object[]
                generator.LoadInt32(arrayLiteral.Count);
                generator.NewArray(typeof(object));
                for (int i = 0; i < arrayLiteral.Count; i++)
                {
                    // Operands for StoreArrayElement() are: an array (object[]), index (int), value (object).
                    // Array
                    generator.Duplicate();

                    // Index
                    generator.LoadInt32(i);

                    // Value
                    var elementExpression = arrayLiteral[i];
                    if (elementExpression == null)
                    {
                        generator.LoadNull();
                    }
                    else
                    {
                        elementExpression.GenerateCode(generator, optimizationInfo);
                        EmitConversion.ToAny(generator, elementExpression.ResultType);
                    }

                    // Store the element value.
                    generator.StoreArrayElement(typeof(object));
                }

                // ArrayConstructor.New(object[])
                generator.Call(ReflectionHelpers.Array_New);
            }
            else if (this.Value is Dictionary <string, object> )
            {
                // This is an object literal.
                var properties = (Dictionary <string, object>) this.Value;

                // Create a new object.
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Object);
                generator.Call(ReflectionHelpers.Object_Construct);

                foreach (var keyValuePair in properties)
                {
                    string propertyName  = keyValuePair.Key;
                    object propertyValue = keyValuePair.Value;

                    generator.Duplicate();
                    generator.LoadString(propertyName);
                    if (propertyValue is Expression)
                    {
                        // Add a new property to the object.
                        var dataPropertyValue = (Expression)propertyValue;
                        dataPropertyValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (dataPropertyValue is FunctionExpression)
                        {
                            ((FunctionExpression)dataPropertyValue).GenerateDisplayName(generator, optimizationInfo, propertyName, false);
                        }
                        EmitConversion.ToAny(generator, dataPropertyValue.ResultType);
                        generator.LoadBoolean(optimizationInfo.StrictMode);
                        generator.Call(ReflectionHelpers.ObjectInstance_SetPropertyValue_String);
                    }
                    else if (propertyValue is Parser.ObjectLiteralAccessor)
                    {
                        // Add a new getter/setter to the object.
                        var accessorValue = (Parser.ObjectLiteralAccessor)propertyValue;
                        if (accessorValue.Getter != null)
                        {
                            accessorValue.Getter.GenerateCode(generator, optimizationInfo);
                            // Support the inferred function displayName property.
                            accessorValue.Getter.GenerateDisplayName(generator, optimizationInfo, "get " + propertyName, true);
                            EmitConversion.ToAny(generator, accessorValue.Getter.ResultType);
                        }
                        else
                        {
                            generator.LoadNull();
                        }
                        if (accessorValue.Setter != null)
                        {
                            accessorValue.Setter.GenerateCode(generator, optimizationInfo);
                            // Support the inferred function displayName property.
                            accessorValue.Setter.GenerateDisplayName(generator, optimizationInfo, "set " + propertyName, true);
                            EmitConversion.ToAny(generator, accessorValue.Setter.ResultType);
                        }
                        else
                        {
                            generator.LoadNull();
                        }
                        generator.LoadInt32((int)Library.PropertyAttributes.FullAccess);
                        generator.NewObject(ReflectionHelpers.PropertyDescriptor_Constructor3);
                        generator.LoadBoolean(false);
                        generator.Call(ReflectionHelpers.ObjectInstance_DefineProperty);
                        generator.Pop();
                    }
                    else
                    {
                        throw new InvalidOperationException("Invalid property value type in object literal.");
                    }
                }
            }
            else
            {
                throw new NotImplementedException("Unknown literal type.");
            }
        }
예제 #10
0
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Generate a new method.
            this.context.GenerateCode();

            // Add the generated method to the nested function list.
            if (optimizationInfo.NestedFunctions == null)
            {
                optimizationInfo.NestedFunctions = new List <GeneratedMethod>();
            }
            optimizationInfo.NestedFunctions.Add(this.context.GeneratedMethod);

            // Add all the nested methods to the parent list.
            if (this.context.GeneratedMethod.Dependencies != null)
            {
                foreach (var nestedFunctionExpression in this.context.GeneratedMethod.Dependencies)
                {
                    optimizationInfo.NestedFunctions.Add(nestedFunctionExpression);
                }
            }

            // Store the generated method in the cache.
            long generatedMethodID = GeneratedMethod.Save(this.context.GeneratedMethod);

            // Create a UserDefinedFunction.

            // prototype
            EmitHelpers.LoadScriptEngine(generator);
            generator.Call(ReflectionHelpers.ScriptEngine_Function);
            generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);

            // name
            if (this.context.DeclarationType == FunctionDeclarationType.Getter)
            {
                generator.LoadString("get " + this.FunctionName);
            }
            else if (this.context.DeclarationType == FunctionDeclarationType.Setter)
            {
                generator.LoadString("set " + this.FunctionName);
            }
            else
            {
                generator.LoadString(this.FunctionName);
            }

            // argumentNames
            generator.LoadInt32(this.Arguments.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < this.Arguments.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadString(this.Arguments[i].Name);
                generator.StoreArrayElement(typeof(string));
            }

            // scope
            EmitHelpers.LoadScope(generator);

            // bodyText
            generator.LoadString(this.BodyText);

            // body
            generator.LoadInt64(generatedMethodID);
            generator.Call(ReflectionHelpers.GeneratedMethod_Load);

            // strictMode
            generator.LoadBoolean(this.context.StrictMode);

            // new UserDefinedFunction(ObjectInstance prototype, string name, IList<string> argumentNames, DeclarativeScope scope, Func<Scope, object, object[], object> body, bool strictMode)
            generator.NewObject(ReflectionHelpers.UserDefinedFunction_Constructor);
        }
예제 #11
0
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Literals cannot have side-effects so if a return value is not expected then generate
            // nothing.
            //if (optimizationInfo.SuppressReturnValue == true)
            //    return;

            if (this.Value is int)
            {
                generator.LoadInt32((int)this.Value);
            }
            else if (this.Value is double)
            {
                generator.LoadDouble((double)this.Value);
            }
            else if (this.Value is string)
            {
                generator.LoadString((string)this.Value);
            }
            else if (this.Value is bool)
            {
                generator.LoadBoolean((bool)this.Value);
            }
            else if (this.Value is RegularExpressionLiteral)
            {
                // RegExp
                var sharedRegExpVariable = optimizationInfo.GetRegExpVariable(generator, (RegularExpressionLiteral)this.Value);
                var label1 = generator.CreateLabel();
                var label2 = generator.CreateLabel();

                // if (sharedRegExp == null) {
                generator.LoadVariable(sharedRegExpVariable);
                generator.BranchIfNotNull(label1);

                // sharedRegExp = Global.RegExp.Construct(source, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Pattern);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Flags);
                generator.Call(ReflectionHelpers.RegExp_Construct);
                generator.Duplicate();
                generator.StoreVariable(sharedRegExpVariable);

                // } else {
                generator.Branch(label2);
                generator.DefineLabelPosition(label1);

                // Global.RegExp.Construct(sharedRegExp, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.Call(ReflectionHelpers.RegExp_Construct);

                // }
                generator.DefineLabelPosition(label2);
            }
            else if (this.Value == Null.Value)
            {
                // Null.
                EmitHelpers.EmitNull(generator);
            }
            else if (this.Value == Undefined.Value)
            {
                // Undefined.
                EmitHelpers.EmitUndefined(generator);
            }
            else
            {
                throw new NotImplementedException("Unknown literal type.");
            }
        }
예제 #12
0
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Note: we use GetRawOperand() so that grouping operators are not ignored.
            var operand = this.GetRawOperand(0);

            // There is only one operand, and it can be either a reference or a function call.
            // We need to split the operand into a function and some arguments.
            // If the operand is a reference, it is equivalent to a function call with no arguments.
            if (operand is FunctionCallExpression)
            {
                // Emit the function instance first.
                var function = ((FunctionCallExpression)operand).Target;
                function.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, function.ResultType);
            }
            else
            {
                // Emit the function instance first.
                operand.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, operand.ResultType);
            }

            // Check the object really is a function - if not, throw an exception.
            generator.IsInstance(typeof(Library.FunctionInstance));
            generator.Duplicate();
            var endOfTypeCheck = generator.CreateLabel();

            generator.BranchIfNotNull(endOfTypeCheck);

            // Throw an nicely formatted exception.
            var targetValue = generator.CreateTemporaryVariable(typeof(object));

            generator.StoreVariable(targetValue);
            EmitHelpers.LoadScriptEngine(generator);
            generator.LoadString("TypeError");
            generator.LoadString("The new operator requires a function, found a '{0}' instead");
            generator.LoadInt32(1);
            generator.NewArray(typeof(object));
            generator.Duplicate();
            generator.LoadInt32(0);
            generator.LoadVariable(targetValue);
            generator.Call(ReflectionHelpers.TypeUtilities_TypeOf);
            generator.StoreArrayElement(typeof(object));
            generator.Call(ReflectionHelpers.String_Format);
            generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error);
            generator.Throw();
            generator.DefineLabelPosition(endOfTypeCheck);
            generator.ReleaseTemporaryVariable(targetValue);

            if (operand is FunctionCallExpression)
            {
                // Emit an array containing the function arguments.
                ((FunctionCallExpression)operand).GenerateArgumentsArray(generator, optimizationInfo);
            }
            else
            {
                // Emit an empty array.
                generator.LoadInt32(0);
                generator.NewArray(typeof(object));
            }

            // Call FunctionInstance.ConstructLateBound(argumentValues)
            generator.Call(ReflectionHelpers.FunctionInstance_ConstructLateBound);
        }
예제 #13
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Generate code for the start of the statement.
            var statementLocals = new StatementLocals()
            {
                NonDefaultBreakStatementBehavior = true, NonDefaultSourceSpanBehavior = true
            };

            GenerateStartOfStatement(generator, optimizationInfo, statementLocals);

            // Construct a loop expression.
            // var enumerator = TypeUtilities.EnumeratePropertyNames(rhs).GetEnumerator();
            // while (true) {
            //   continue-target:
            //   if (enumerator.MoveNext() == false)
            //     goto break-target;
            //   lhs = enumerator.Current;
            //
            //   <body statements>
            // }
            // break-target:

            // Call IEnumerable<string> EnumeratePropertyNames(ScriptEngine engine, object obj)
            optimizationInfo.MarkSequencePoint(generator, this.TargetObjectSourceSpan);
            EmitHelpers.LoadScriptEngine(generator);
            this.TargetObject.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToAny(generator, this.TargetObject.ResultType);
            generator.Call(ReflectionHelpers.TypeUtilities_EnumeratePropertyNames);

            // Call IEnumerable<string>.GetEnumerator()
            generator.Call(ReflectionHelpers.IEnumerable_String_GetEnumerator);

            // Store the enumerator in a temporary variable.
            var enumerator = generator.CreateTemporaryVariable(typeof(IEnumerator <string>));

            generator.StoreVariable(enumerator);

            var breakTarget    = generator.CreateLabel();
            var continueTarget = generator.DefineLabelPosition();

            // Generate the scope variable if necessary.
            this.Scope.GenerateScopeCreation(generator, optimizationInfo);

            //   if (enumerator.MoveNext() == false)
            //     goto break-target;
            generator.LoadVariable(enumerator);
            generator.Call(ReflectionHelpers.IEnumerator_MoveNext);
            generator.BranchIfFalse(breakTarget);

            // lhs = enumerator.Current;
            this.Variable.GenerateReference(generator, optimizationInfo);
            generator.LoadVariable(enumerator);
            generator.Call(ReflectionHelpers.IEnumerator_String_Current);
            this.Variable.GenerateSet(generator, optimizationInfo, PrimitiveType.String);

            // Emit the body statement(s).
            optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget, continueTarget, labelledOnly: false);
            this.Body.GenerateCode(generator, optimizationInfo);
            optimizationInfo.PopBreakOrContinueInfo();

            generator.Branch(continueTarget);
            generator.DefineLabelPosition(breakTarget);

            // Generate code for the end of the statement.
            GenerateEndOfStatement(generator, optimizationInfo, statementLocals);
        }
예제 #14
0
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // If the class was named, then we need to create a new scope to hold the name.
            if (Name != null)
            {
                Scope.GenerateScopeCreation(generator, optimizationInfo);
            }

            // engine
            EmitHelpers.LoadScriptEngine(generator);

            // name
            generator.LoadStringOrNull(this.Name);

            // extends
            if (Extends == null)
            {
                generator.LoadNull();
            }
            else
            {
                Extends.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, Extends.ResultType);
            }

            // constructor
            if (Constructor == null)
            {
                generator.LoadNull();
            }
            else
            {
                Constructor.GenerateCode(generator, optimizationInfo);
            }

            // ConstructClass(ScriptEngine engine, string name, object extends, FunctionInstance constructor)
            generator.CallStatic(ReflectionHelpers.ReflectionHelpers_ConstructClass);

            // Create a variable to hold the container instance value.
            var containerVariable = generator.CreateTemporaryVariable(typeof(ObjectInstance));

            foreach (var member in this.Members)
            {
                // class.InstancePrototype
                generator.Duplicate();
                if (!member.Name.IsStatic)
                {
                    generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);
                }

                // Store this in a variable so that FunctionExpression.GenerateCode can retrieve it.
                generator.Duplicate();
                generator.StoreVariable(containerVariable);

                // The key can be a property name or an expression that evaluates to a name.
                if (member.Name.HasStaticName)
                {
                    generator.LoadString(member.Name.StaticName);
                }
                else
                {
                    member.Name.ComputedName.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToPropertyKey(generator, member.Name.ComputedName.ResultType);
                }

                // Emit the function value.
                member.ContainerVariable = containerVariable;
                member.GenerateCode(generator, optimizationInfo);
                member.ContainerVariable = null;

                if (member.Name.IsGetter)
                {
                    // Add a getter to the object.
                    generator.Call(ReflectionHelpers.ReflectionHelpers_SetClassGetter);
                }
                else if (member.Name.IsSetter)
                {
                    // Add a setter to the object.
                    generator.Call(ReflectionHelpers.ReflectionHelpers_SetClassSetter);
                }
                else
                {
                    // Add a new property to the object.
                    generator.Call(ReflectionHelpers.ReflectionHelpers_SetClassValue);
                }
            }

            // Release the variable that we created above.
            generator.ReleaseTemporaryVariable(containerVariable);

            // Store the class name in the scope.
            if (Name != null)
            {
                generator.Duplicate();
                new NameExpression(Scope, Name).GenerateSet(generator, optimizationInfo, PrimitiveType.Object);
            }
        }
예제 #15
0
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Generate a new method.
            this.context.GenerateCode();

            // Add the generated method to the nested function list.
            if (optimizationInfo.NestedFunctions == null)
            {
                optimizationInfo.NestedFunctions = new List <GeneratedMethod>();
            }
            optimizationInfo.NestedFunctions.Add(this.context.GeneratedMethod);

            // Add all the nested methods to the parent list.
            if (this.context.GeneratedMethod.Dependencies != null)
            {
                foreach (var nestedFunctionExpression in this.context.GeneratedMethod.Dependencies)
                {
                    optimizationInfo.NestedFunctions.Add(nestedFunctionExpression);
                }
            }

            // Store the generated method in the cache.
            long generatedMethodID = GeneratedMethod.Save(this.context.GeneratedMethod);

            // Create a UserDefinedFunction.

            // prototype
            EmitHelpers.LoadScriptEngine(generator);
            generator.Call(ReflectionHelpers.ScriptEngine_Function);
            generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);

            // name
            string prefix = null;

            if (Name.IsGetter)
            {
                prefix = "get ";
            }
            else if (Name.IsSetter)
            {
                prefix = "set ";
            }
            if (Name.HasStaticName)
            {
                generator.LoadString(prefix + Name.StaticName);
            }
            else
            {
                // Compute the name at runtime.
                if (prefix != null)
                {
                    generator.LoadString(prefix);
                }
                Name.ComputedName.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToString(generator, Name.ComputedName.ResultType);
                if (prefix != null)
                {
                    generator.CallStatic(ReflectionHelpers.String_Concat_String_String);
                }
            }

            // argumentNames
            generator.LoadInt32(this.Arguments.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < this.Arguments.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadString(this.Arguments[i].Name);
                generator.StoreArrayElement(typeof(string));
            }

            // scope
            Scope.GenerateReference(generator, optimizationInfo);

            // bodyText
            generator.LoadString(this.BodyText);

            // body
            generator.LoadInt64(generatedMethodID);
            generator.Call(ReflectionHelpers.GeneratedMethod_Load);

            // strictMode
            generator.LoadBoolean(this.context.StrictMode);

            // container
            if (ContainerVariable != null)
            {
                generator.LoadVariable(ContainerVariable);
            }
            else
            {
                generator.LoadNull();
            }

            // CreateFunction(ObjectInstance prototype, string name, IList<string> argumentNames,
            //   RuntimeScope scope, Func<Scope, object, object[], object> body,
            //   bool strictMode, FunctionInstance container)
            generator.CallStatic(ReflectionHelpers.ReflectionHelpers_CreateFunction);
        }
        /// <summary>
        /// Generates CIL for the statement.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Generate code for the start of the statement.
            var statementLocals = new StatementLocals() { NonDefaultSourceSpanBehavior = true };
            GenerateStartOfStatement(generator, optimizationInfo, statementLocals);

            // Unlike in .NET, in javascript there are no restrictions on what can appear inside
            // try, catch and finally blocks.  The one restriction which causes problems is the
            // inability to jump out of .NET finally blocks.  This is required when break, continue
            // or return statements appear inside of a finally block.  To work around this, when
            // inside a finally block these instructions throw an exception instead.

            // Setting the InsideTryCatchOrFinally flag converts BR instructions into LEAVE
            // instructions so that the finally block is executed correctly.
            var previousInsideTryCatchOrFinally = optimizationInfo.InsideTryCatchOrFinally;
            optimizationInfo.InsideTryCatchOrFinally = true;

            // Finally requires two exception nested blocks.
            if (this.FinallyBlock != null)
                generator.BeginExceptionBlock();

            // Begin the exception block.
            generator.BeginExceptionBlock();

            // Generate code for the try block.
            this.TryBlock.GenerateCode(generator, optimizationInfo);

            // Generate code for the catch block.
            ILLocalVariable skipFinallyBlock = null;
           
            
            // Begin a catch block.  The exception is on the top of the stack.
            generator.BeginCatchBlock(typeof(Exception));

            // Check the exception is catchable by calling CanCatchException(ex).
            // We need to handle the case where JS code calls into .NET code which then throws
            // a JavaScriptException from a different ScriptEngine.
            // If CatchBlock is null, we need to rethrow the exception in every case.
            var endOfIfLabel = generator.CreateLabel();
            generator.Duplicate();  // ex
            var exceptionTemporary = generator.CreateTemporaryVariable(typeof(Exception));
            generator.StoreVariable(exceptionTemporary);
            EmitHelpers.LoadScriptEngine(generator);
            generator.LoadVariable(exceptionTemporary);
            generator.ReleaseTemporaryVariable(exceptionTemporary);
            generator.Call(ReflectionHelpers.ScriptEngine_CanCatchException);
            generator.BranchIfTrue(endOfIfLabel);
            if (this.FinallyBlock != null)
            {
                generator.LoadBoolean(true);
                skipFinallyBlock = generator.DeclareVariable(typeof(bool), "skipFinallyBlock");
                generator.StoreVariable(skipFinallyBlock);
            }
            if (this.CatchBlock == null)
                generator.DefineLabelPosition(endOfIfLabel);
            generator.Rethrow();
            if (this.CatchBlock != null)
                generator.DefineLabelPosition(endOfIfLabel);

            if (this.CatchBlock != null) {
                // Create a new DeclarativeScope.
                this.CatchScope.GenerateScopeCreation(generator, optimizationInfo);

                // Store the error object in the variable provided.
                generator.Call(ReflectionHelpers.JavaScriptException_ErrorObject);
                var catchVariable = new NameExpression(this.CatchScope, this.CatchVariableName);
                catchVariable.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);

                // Make sure the scope is reverted even if an exception is thrown.
                generator.BeginExceptionBlock();

                // Emit code for the statements within the catch block.
                this.CatchBlock.GenerateCode(generator, optimizationInfo);

                // Revert the scope.
                generator.BeginFinallyBlock();
                this.CatchScope.GenerateScopeDestruction(generator, optimizationInfo);
                generator.EndExceptionBlock();
            }

            // Generate code for the finally block.
            if (this.FinallyBlock != null)
            {
                generator.BeginFinallyBlock();

                // If an exception was thrown that wasn't handled by the catch block, then don't
                // run the finally block either.  This prevents user code from being run when a
                // ThreadAbortException is thrown.
                var endOfFinallyBlock = generator.CreateLabel();                
                generator.LoadVariable(skipFinallyBlock);
                generator.BranchIfTrue(endOfFinallyBlock);

                var branches = new List<ILLabel>();
                var previousStackSize = optimizationInfo.LongJumpStackSizeThreshold;
                optimizationInfo.LongJumpStackSizeThreshold = optimizationInfo.BreakOrContinueStackSize;
                var previousCallback = optimizationInfo.LongJumpCallback;
                optimizationInfo.LongJumpCallback = (generator2, label) =>
                    {
                        // It is not possible to branch out of a finally block - therefore instead of
                        // generating LEAVE instructions we throw an exception then catch it to transfer
                        // control out of the finally block.
                        generator2.LoadInt32(branches.Count);
                        generator2.NewObject(ReflectionHelpers.LongJumpException_Constructor);
                        generator2.Throw();

                        // Record any branches that are made within the finally code.
                        branches.Add(label);
                    };

                // Emit code for the finally block.
                this.FinallyBlock.GenerateCode(generator, optimizationInfo);

                // Define the position at the end of the finally block.
                generator.DefineLabelPosition(endOfFinallyBlock);

                // End the main exception block.
                generator.EndExceptionBlock();

                // Begin a catch block to catch any LongJumpExceptions. The exception object is on
                // the top of the stack.
                generator.BeginCatchBlock(typeof(LongJumpException));

                if (branches.Count > 0)
                {
                    // switch (exception.RouteID)
                    // {
                    //    case 0: goto label1;
                    //    case 1: goto label2;
                    // }
                    ILLabel[] switchLabels = new ILLabel[branches.Count];
                    for (int i = 0; i < branches.Count; i++)
                        switchLabels[i] = generator.CreateLabel();
                    generator.Call(ReflectionHelpers.LongJumpException_RouteID);
                    generator.Switch(switchLabels);
                    for (int i = 0; i < branches.Count; i++)
                    {
                        generator.DefineLabelPosition(switchLabels[i]);
                        generator.Leave(branches[i]);
                    }
                }

                // Reset the state we clobbered.
                optimizationInfo.LongJumpStackSizeThreshold = previousStackSize;
                optimizationInfo.LongJumpCallback = previousCallback;
            }

            // End the exception block.
            generator.EndExceptionBlock();

            // Reset the InsideTryCatchOrFinally flag.
            optimizationInfo.InsideTryCatchOrFinally = previousInsideTryCatchOrFinally;

            // Generate code for the end of the statement.
            GenerateEndOfStatement(generator, optimizationInfo, statementLocals);
        }
예제 #17
0
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Literals cannot have side-effects so if a return value is not expected then generate
            // nothing.
            //if (optimizationInfo.SuppressReturnValue == true)
            //    return;

            if (this.Value is int)
            {
                generator.LoadInt32((int)this.Value);
            }
            else if (this.Value is double)
            {
                generator.LoadDouble((double)this.Value);
            }
            else if (this.Value is string)
            {
                generator.LoadString((string)this.Value);
            }
            else if (this.Value is bool)
            {
                generator.LoadBoolean((bool)this.Value);
            }
            else if (this.Value is RegularExpressionLiteral)
            {
                // RegExp
                var sharedRegExpVariable = optimizationInfo.GetRegExpVariable(generator, (RegularExpressionLiteral)this.Value);
                var label1 = generator.CreateLabel();
                var label2 = generator.CreateLabel();

                // if (sharedRegExp == null) {
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.BranchIfNotEqual(label1);

                // sharedRegExp = Global.RegExp.Construct(source, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Pattern);
                generator.LoadString(((RegularExpressionLiteral)this.Value).Flags);
                generator.Call(ReflectionHelpers.RegExp_Construct);
                generator.Duplicate();
                generator.StoreVariable(sharedRegExpVariable);

                // } else {
                generator.Branch(label2);
                generator.DefineLabelPosition(label1);

                // Global.RegExp.Construct(sharedRegExp, flags)
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_RegExp);
                generator.LoadVariable(sharedRegExpVariable);
                generator.LoadNull();
                generator.Call(ReflectionHelpers.RegExp_Construct);

                // }
                generator.DefineLabelPosition(label2);
            }
            else if (this.Value == Null.Value)
            {
                // Null.
                EmitHelpers.EmitNull(generator);
            }
            else if (this.Value == Undefined.Value)
            {
                // Undefined.
                EmitHelpers.EmitUndefined(generator);
            }
            else if (this.Value is List <Expression> )
            {
                // Construct an array literal.
                var arrayLiteral = (List <Expression>) this.Value;

                // Operands for ArrayConstructor.New() are: an ArrayConstructor instance (ArrayConstructor), an array (object[])
                // ArrayConstructor
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Array);

                // object[]
                generator.LoadInt32(arrayLiteral.Count);
                generator.NewArray(typeof(object));
                for (int i = 0; i < arrayLiteral.Count; i++)
                {
                    // Operands for StoreArrayElement() are: an array (object[]), index (int), value (object).
                    // Array
                    generator.Duplicate();

                    // Index
                    generator.LoadInt32(i);

                    // Value
                    var elementExpression = arrayLiteral[i];
                    if (elementExpression == null)
                    {
                        generator.LoadNull();
                    }
                    else
                    {
                        elementExpression.GenerateCode(generator, optimizationInfo);
                        EmitConversion.ToAny(generator, elementExpression.ResultType);
                    }

                    // Store the element value.
                    generator.StoreArrayElement(typeof(object));
                }

                // ArrayConstructor.New(object[])
                generator.Call(ReflectionHelpers.Array_New);
            }
            else if (this.Value is List <KeyValuePair <Expression, Expression> > )
            {
                // This is an object literal.
                var properties = (List <KeyValuePair <Expression, Expression> >) this.Value;

                // Create a new object.
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Object);
                generator.Call(ReflectionHelpers.Object_Construct);

                foreach (var keyValuePair in properties)
                {
                    Expression propertyName  = keyValuePair.Key;
                    Expression propertyValue = keyValuePair.Value;

                    generator.Duplicate();

                    // The key can be a property name or an expression that evaluates to a name.
                    propertyName.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToPropertyKey(generator, propertyName.ResultType);

                    var functionValue = propertyValue as FunctionExpression;
                    if (functionValue != null && functionValue.DeclarationType == FunctionDeclarationType.Getter)
                    {
                        // Add a getter to the object.
                        functionValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
                        {
                            functionValue.GenerateDisplayName(generator, optimizationInfo, "get " + (string)((LiteralExpression)propertyName).Value, true);
                        }
                        generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralGetter);
                    }
                    else if (functionValue != null && functionValue.DeclarationType == FunctionDeclarationType.Setter)
                    {
                        // Add a setter to the object.
                        functionValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
                        {
                            functionValue.GenerateDisplayName(generator, optimizationInfo, "set " + (string)((LiteralExpression)propertyName).Value, true);
                        }
                        generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralSetter);
                    }
                    else
                    {
                        // Add a new property to the object.
                        propertyValue.GenerateCode(generator, optimizationInfo);
                        // Support the inferred function displayName property.
                        if (propertyValue is FunctionExpression && propertyName is LiteralExpression && ((LiteralExpression)propertyName).Value is string)
                        {
                            ((FunctionExpression)propertyValue).GenerateDisplayName(generator, optimizationInfo, (string)((LiteralExpression)propertyName).Value, false);
                        }
                        EmitConversion.ToAny(generator, propertyValue.ResultType);
                        generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralValue);
                    }
                }
            }
            else
            {
                throw new NotImplementedException("Unknown literal type.");
            }
        }
예제 #18
0
        /// <summary>
        /// Generates an array containing the argument values for a tagged template literal.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="templateLiteral"> The template literal expression containing the parameter
        /// values. </param>
        internal void GenerateTemplateArgumentsArray(ILGenerator generator, OptimizationInfo optimizationInfo, TemplateLiteralExpression templateLiteral)
        {
            // Generate an array containing the value of each argument.
            generator.LoadInt32(templateLiteral.Values.Count + 1);
            generator.NewArray(typeof(object));

            // Load the first parameter.
            generator.Duplicate();
            generator.LoadInt32(0);

            // Generate a unique integer that is used as the cache key.
            int callSiteId = System.Threading.Interlocked.Increment(ref templateCallSiteId);

            // Call GetCachedTemplateStringsArray(ScriptEngine engine, int callSiteId)
            EmitHelpers.LoadScriptEngine(generator);
            generator.LoadInt32(callSiteId);
            generator.CallStatic(ReflectionHelpers.ReflectionHelpers_GetCachedTemplateStringsArray);

            // If that's null, do it the long way.
            var afterCreateTemplateStringsArray = generator.CreateLabel();

            generator.Duplicate();
            generator.BranchIfNotNull(afterCreateTemplateStringsArray);
            generator.Pop();

            // Start emitting arguments for CreateTemplateStringsArray.
            EmitHelpers.LoadScriptEngine(generator);

            // int callSiteId
            generator.LoadInt32(callSiteId);

            // string[] strings
            generator.LoadInt32(templateLiteral.Strings.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < templateLiteral.Strings.Count; i++)
            {
                // strings[i] = templateLiteral.Strings[i]
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadString(templateLiteral.Strings[i]);
                generator.StoreArrayElement(typeof(string));
            }

            // string[] raw
            generator.LoadInt32(templateLiteral.RawStrings.Count);
            generator.NewArray(typeof(string));
            for (int i = 0; i < templateLiteral.RawStrings.Count; i++)
            {
                // raw[i] = templateLiteral.RawStrings[i]
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadString(templateLiteral.RawStrings[i]);
                generator.StoreArrayElement(typeof(string));
            }

            // CreateTemplateStringsArray(ScriptEngine engine, int callSiteId, object[] strings, object[] rawStrings)
            generator.CallStatic(ReflectionHelpers.ReflectionHelpers_CreateTemplateStringsArray);
            generator.DefineLabelPosition(afterCreateTemplateStringsArray);

            // Store in the array.
            generator.StoreArrayElement(typeof(object));

            // Values are passed as subsequent parameters.
            for (int i = 0; i < templateLiteral.Values.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i + 1);
                templateLiteral.Values[i].GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, templateLiteral.Values[i].ResultType);
                generator.StoreArrayElement(typeof(object));
            }
        }
        /// <summary>
        /// Generates IL for the script.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        protected override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Method signature: object FunctionDelegate(Compiler.Scope scope, object thisObject, Library.FunctionInstance functionObject, object[] arguments)

            // Initialize the scope (note: the initial scope for a function is always declarative).
            this.InitialScope.GenerateScopeCreation(generator, optimizationInfo);

            // Verify the scope is correct.
            VerifyScope(generator);

            // In ES3 the "this" value must be an object.  See 10.4.3 in the spec.
            if (this.StrictMode == false && this.MethodOptimizationHints.HasThis == true)
            {
                // if (thisObject == null || thisObject == Null.Value || thisObject == Undefined.Value)
                EmitHelpers.LoadThis(generator);
                generator.LoadNull();
                generator.CompareEqual();
                EmitHelpers.LoadThis(generator);
                EmitHelpers.EmitNull(generator);
                generator.CompareEqual();
                generator.BitwiseOr();
                EmitHelpers.LoadThis(generator);
                EmitHelpers.EmitUndefined(generator);
                generator.CompareEqual();
                generator.BitwiseOr();

                // {
                var startOfFalse = generator.CreateLabel();
                generator.BranchIfFalse(startOfFalse);

                // thisObject = engine.Global;
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Global);

                // } else {
                var endOfIf = generator.CreateLabel();
                generator.Branch(endOfIf);
                generator.DefineLabelPosition(startOfFalse);

                // thisObject = TypeConverter.ToObject(thisObject);
                EmitHelpers.LoadThis(generator);
                EmitConversion.ToObject(generator, PrimitiveType.Any, optimizationInfo);

                // }
                generator.DefineLabelPosition(endOfIf);
                EmitHelpers.StoreThis(generator);
            }

            // Transfer the function name into the scope.
            if (string.IsNullOrEmpty(this.Name) == false &&
                this.IncludeNameInScope == true &&
                this.ArgumentNames.Contains(this.Name) == false &&
                optimizationInfo.MethodOptimizationHints.HasVariable(this.Name))
            {
                EmitHelpers.LoadFunction(generator);
                var functionName = new NameExpression(this.InitialScope, this.Name);
                functionName.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
            }

            // Transfer the arguments object into the scope.
            if (this.MethodOptimizationHints.HasArguments == true && this.ArgumentNames.Contains("arguments") == false)
            {
                // prototype
                EmitHelpers.LoadScriptEngine(generator);
                generator.Call(ReflectionHelpers.ScriptEngine_Object);
                generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype);
                // callee
                EmitHelpers.LoadFunction(generator);
                generator.CastClass(typeof(Library.UserDefinedFunction));
                // scope
                EmitHelpers.LoadScope(generator);
                generator.CastClass(typeof(DeclarativeScope));
                // argumentValues
                EmitHelpers.LoadArgumentsArray(generator);
                generator.NewObject(ReflectionHelpers.Arguments_Constructor);
                var arguments = new NameExpression(this.InitialScope, "arguments");
                arguments.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
            }

            // Transfer the argument values into the scope.
            // Note: the arguments array can be smaller than expected.
            if (this.ArgumentNames.Count > 0)
            {
                var endOfArguments = generator.CreateLabel();
                for (int i = 0; i < this.ArgumentNames.Count; i++)
                {
                    // Check if a duplicate argument name exists.
                    bool duplicate = false;
                    for (int j = i + 1; j < this.ArgumentNames.Count; j++)
                    {
                        if (this.ArgumentNames[i] == this.ArgumentNames[j])
                        {
                            duplicate = true;
                            break;
                        }
                    }
                    if (duplicate == true)
                    {
                        continue;
                    }

                    // Check if an array element exists.
                    EmitHelpers.LoadArgumentsArray(generator);
                    generator.LoadArrayLength();
                    generator.LoadInt32(i);
                    generator.BranchIfLessThanOrEqual(endOfArguments);

                    // Store the array element in the scope.
                    EmitHelpers.LoadArgumentsArray(generator);
                    generator.LoadInt32(i);
                    generator.LoadArrayElement(typeof(object));
                    var argument = new NameExpression(this.InitialScope, this.ArgumentNames[i]);
                    argument.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false);
                }
                generator.DefineLabelPosition(endOfArguments);
            }

            // Initialize any declarations.
            this.InitialScope.GenerateDeclarations(generator, optimizationInfo);

            //EmitHelpers.LoadScope(generator);
            //EmitConversion.ToObject(generator, PrimitiveType.Any);
            //generator.Pop();

            // Generate code for the body of the function.
            this.AbstractSyntaxTree.GenerateCode(generator, optimizationInfo);

            // Define the return target - this is where the return statement jumps to.
            // ReturnTarget can be null if there were no return statements.
            if (optimizationInfo.ReturnTarget != null)
            {
                generator.DefineLabelPosition(optimizationInfo.ReturnTarget);
            }

            // Load the return value.  If the variable is null, there were no return statements.
            if (optimizationInfo.ReturnVariable != null)
            {
                // Return the value stored in the variable.  Will be null if execution hits the end
                // of the function without encountering any return statements.
                generator.LoadVariable(optimizationInfo.ReturnVariable);
            }
            else
            {
                // There were no return statements - return null.
                generator.LoadNull();
            }
        }
예제 #20
0
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Create a new object.
            EmitHelpers.LoadScriptEngine(generator);
            generator.Call(ReflectionHelpers.ScriptEngine_Object);
            generator.Call(ReflectionHelpers.Object_Construct);

            // Create a variable to hold the container instance value.
            var containerVariable = generator.CreateTemporaryVariable(typeof(ObjectInstance));

            generator.Duplicate();
            generator.StoreVariable(containerVariable);

            foreach (var property in this.Properties)
            {
                generator.Duplicate();

                // The key can be a property name or an expression that evaluates to a name.
                if (property.Name.HasStaticName)
                {
                    generator.LoadString(property.Name.StaticName);
                }
                else
                {
                    property.Name.ComputedName.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToPropertyKey(generator, property.Name.ComputedName.ResultType);
                }

                // Emit the property value.
                if (property.Value is FunctionExpression functionExpression)
                {
                    functionExpression.ContainerVariable = containerVariable;
                    property.Value.GenerateCode(generator, optimizationInfo);
                    generator.ReinterpretCast(typeof(UserDefinedFunction));
                    functionExpression.ContainerVariable = null;
                }
                else
                {
                    property.Value.GenerateCode(generator, optimizationInfo);
                    EmitConversion.ToAny(generator, property.Value.ResultType);
                }

                if (property.Name.IsGetter)
                {
                    // Add a getter to the object.
                    generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralGetter);
                }
                else if (property.Name.IsSetter)
                {
                    // Add a setter to the object.
                    generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralSetter);
                }
                else
                {
                    // Add a new property to the object.
                    generator.Call(ReflectionHelpers.ReflectionHelpers_SetObjectLiteralValue);
                }
            }

            // Release the variable that we created above.
            generator.ReleaseTemporaryVariable(containerVariable);
        }