private JavaScriptValue NativeCallSyncHook(
            JavaScriptValue callee,
            bool isConstructCall,
            JavaScriptValue[] arguments,
            ushort argumentCount,
            IntPtr callbackData)
        {
            if (argumentCount != 4)
            {
                throw new ArgumentOutOfRangeException(nameof(argumentCount), "Expected exactly four arguments (global, moduleId, methodId, and args).");
            }

            if (_callSyncHook == null)
            {
                throw new InvalidOperationException("Sync hook has not been set.");
            }

            var moduleId = (int)arguments[1].ToDouble();
            var methodId = (int)arguments[2].ToDouble();
            var args     = (JArray)ConvertJson(arguments[3]);

            try
            {
                var result = _callSyncHook(moduleId, methodId, args);
                return(ConvertJson(result));
            }
            catch (Exception e)
            {
                var error = JavaScriptValue.CreateError(JavaScriptValue.FromString(e.Message));
                Native.JsSetException(error);
                return(JavaScriptValue.Invalid);
            }
        }
Exemplo n.º 2
0
        private static void ThrowException(string errorString)
        {
            // We ignore error since we're already in an error state.
            JavaScriptValue errorValue  = JavaScriptValue.FromString(errorString);
            JavaScriptValue errorObject = JavaScriptValue.CreateError(errorValue);

            JavaScriptContext.SetException(errorObject);
        }
Exemplo n.º 3
0
        static public JavaScriptValue SetJSException(Exception e)
        {
            var v = JavaScriptValue.CreateExternalObject(GCHandle.ToIntPtr(GCHandle.Alloc(e)), FreeDg);

            v.AddRef();
            v.SetIndexedProperty(JavaScriptValue.FromString("toString"), JavaScriptValue.FromString(e.ToString()));
            Native.JsSetException(JavaScriptValue.CreateError(v));
            return(JavaScriptValue.Invalid);
        }
Exemplo n.º 4
0
 static JavaScriptValue TestJSNativeFunction2(JavaScriptValue callee,
                                              [MarshalAs(UnmanagedType.U1)] bool isConstructCall,
                                              [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] JavaScriptValue[] arguments,
                                              ushort argumentCount,
                                              IntPtr callbackData)
 {
     JavaScriptContext.SetException(JavaScriptValue.CreateError(JavaScriptValue.FromString("test error")));
     return(JavaScriptValue.Invalid);
 }
Exemplo n.º 5
0
        JavaScriptErrorCode FetchImportedModuleCallback(
            JavaScriptModuleRecord referencingModule,
            JavaScriptValue specifierAsValue,
            out JavaScriptModuleRecord outDependentModuleRecord
            )
        {
            string specifier = specifierAsValue.ToString();

            Loader.Debug($"Javascript.Module.RecordDelegate FetchImportedModuleCallback for specifier: '{specifier}'");

            string normalizedSpecifier = resolver.Normalize(referencingModule.HostUrl, specifier);

            JavaScriptModuleRecord dependentModuleRecord;

            if (normalizedSpecifier == null)
            {
                dependentModuleRecord           = JavaScriptModuleRecord.Initialize(null, "<invalid record>");
                dependentModuleRecord.Exception = JavaScriptValue.CreateError($"Could not find module '{specifier}' from '{referencingModule.HostUrl}'");
            }
            else if (cache.Has(normalizedSpecifier))
            {
                dependentModuleRecord = cache.GetOrInvalid(normalizedSpecifier);
            }
            else
            {
                dependentModuleRecord         = JavaScriptModuleRecord.Initialize(referencingModule, normalizedSpecifier);
                dependentModuleRecord.HostUrl = normalizedSpecifier;
                cache.Set(normalizedSpecifier, dependentModuleRecord);

                moduleParseQueue.Enqueue(() => {
                    Loader.Debug($"Javascript.Module.RecordDelegate parsing source for '{specifier}'");
                    string source = "";
                    try {
                        source = resolver.Read(normalizedSpecifier);
                    } catch (Exception loadException) {
                        dependentModuleRecord.Exception = JavaScriptValue.CreateError($"Couldn't read file '{normalizedSpecifier}': " + loadException);
                    }

                    try {
                        // if we couldn't read the file for whatever reason, we must still call ParseSource
                        // so that the internals will move on to the next step and show us the Exception set above
                        dependentModuleRecord.ParseSource(source); // can throw syntax errors
                    } catch {
                        // will set Exception for us!
                    }
                });
            }

            dependencies.Add(dependentModuleRecord);

            outDependentModuleRecord = dependentModuleRecord;
            return(JavaScriptErrorCode.NoError); // Error case gets handled by Exception being set on the module record
        }
Exemplo n.º 6
0
 static JavaScriptValue body(JavaScriptValue callee,
                             [MarshalAs(UnmanagedType.U1)] bool isConstructCall,
                             [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] JavaScriptValue[] arguments,
                             ushort argumentCount,
                             IntPtr callbackData)
 {
     try
     {
         var that        = (OverloadSelector)GCHandle.FromIntPtr(callbackData).Target;
         var lastIdx     = -1;
         var lowestScore = OverloadEntry.DENIED - 1; // block denied
         for (int i = 0; i < that.methodInfos.Count; i++)
         {
             var mi    = that.methodInfos[i];
             var score = mi.GetArgumentsScore(arguments);
             if (lowestScore > score)
             {
                 lowestScore = score;
                 lastIdx     = i;
             }
             else if (lowestScore == score)
             {
                 lastIdx = -1; // deny ambiguous overload
             }
         }
         if (lastIdx == -1)
         {
             Native.JsSetException(JavaScriptValue.CreateError(JavaScriptValue.FromString("ambiguous overload " + that.GetName())));
             return(JavaScriptValue.Invalid);
         }
         var method = that.methodInfos[lastIdx];
         if (method.cachedFunction == null)
         {
             method.cachedFunction = method.entityWrapper.Wrap();
         }
         if (!method.cachedData.IsAllocated)
         {
             method.cachedData = GCHandle.Alloc(method.entityWrapper);
         }
         return(method.cachedFunction(callee, isConstructCall, arguments, argumentCount, GCHandle.ToIntPtr(method.cachedData)));
     }
     catch (Exception e)
     {
         return(ExceptionUtil.SetJSException(e));
     }
 }
        public static JavaScriptValue Base64Encode(JavaScriptValue callee, bool isConstructCall, JavaScriptValue[] arguments,
                                                   ushort argumentCount, IntPtr callbackData)
        {
            if (arguments.Count() >= 2)
            {
                try
                {
                    var stringToEncode = arguments[1].ConvertToString().ToString();

                    return(JavaScriptValue.FromString(Convert.ToBase64String(Encoding.UTF8.GetBytes(stringToEncode))));
                }
                catch (Exception e)
                {
                    return(JavaScriptValue.CreateError(JavaScriptValue.FromString(e.Message)));
                }
            }
            return(JavaScriptValue.CreateError(JavaScriptValue.FromString("Not enough arguments")));
        }
Exemplo n.º 8
0
 static JavaScriptValue body(JavaScriptValue callee,
                             [MarshalAs(UnmanagedType.U1)] bool isConstructCall,
                             [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] JavaScriptValue[] arguments,
                             ushort argumentCount,
                             IntPtr callbackData)
 {
     try
     {
         var that = (FunctionWrapper)GCHandle.FromIntPtr(callbackData).Target;
         if (that.constructOnly && !isConstructCall)
         {
             return(JavaScriptValue.Undefined);
         }
         if (arguments.Length - 1 != that.neededArgumentsCount)
         {
             Native.JsSetException(
                 JavaScriptValue.CreateError(
                     JavaScriptValue.FromString(
                         string.Format("Argument count is not satisfacted. needs {0}, got {1}: {2}",
                                       that.neededArgumentsCount, arguments.Length - 1, that.GetName()))));
             return(JavaScriptValue.Invalid);
         }
         if (that.wrapdg == null)
         {
             that.wrapdg = that.WrapFirst();
         }
         var obj = that.wrapdg(arguments);
         var v   = JSValue.FromObject(obj).rawvalue;
         if (isConstructCall)
         {
             var pt = callee.GetIndexedProperty(JavaScriptValue.FromString("prototype"));
             if (pt.IsValid)
             {
                 v.Prototype = pt;
             }
         }
         return(v);
     }
     catch (Exception e)
     {
         return(ExceptionUtil.SetJSException(e));
     }
 }
        public JavaScriptValue CreatePromise(Task <JavaScriptValue> task)
        {
            lock (taskSync)
            {
                outstandingItems++;
            }

            JavaScriptValue resolve;
            JavaScriptValue reject;
            JavaScriptValue promise = JavaScriptValue.CreatePromise(out resolve, out reject);

            reject.AddRef();
            resolve.AddRef();
            task.ContinueWith(
                (antecedent, state) =>
            {
                switch (antecedent.Status)
                {
                case TaskStatus.Canceled:
                case TaskStatus.Faulted:
                    reject.CallFunction(
                        JavaScriptValue.GlobalObject,
                        JavaScriptValue.CreateError(JavaScriptValue.FromString(antecedent.Exception.Message)));
                    break;

                case TaskStatus.RanToCompletion:
                    var result = antecedent.GetAwaiter().GetResult();
                    resolve.CallFunction(JavaScriptValue.GlobalObject, result);
                    break;
                }

                lock (taskSync)
                {
                    outstandingItems--;
                }
                reject.Release();
                resolve.Release();
            },
                null,
                this.taskScheduler);
            return(promise);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Creates a safe function wrapper for the native function to ensure we propagate
        /// errors in javascript appropriately.
        /// </summary>
        public static JavaScriptNativeFunction Decorate(JavaScriptNativeFunction fn)
        {
            return((v, s, args, argLength, data) =>
            {
                try
                {
                    return fn(v, s, args, argLength, data);
                }
                catch (Exception e)
                {
                    // Pass back entire stack trace to ensure all information makes it back through
                    var message = e.ToString();

                    var jsException = JavaScriptValue.CreateError(JavaScriptValue.FromString(message));
                    JavaScriptContext.SetException(jsException);

                    return JavaScriptValue.Invalid;
                }
            });
        }
        public static JavaScriptValue Log(JavaScriptValue callee, bool isConstructCall, JavaScriptValue[] arguments, ushort argumentCount, IntPtr callbackData)
        {
            if (arguments.Count() >= 2)
            {
                ConsoleColor foreground = Console.ForegroundColor;

                try
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("Script debug: " + arguments[1].ConvertToString().ToString(),
                                      arguments.Skip(2).Select(a => a.ConvertToString().ToString()).ToArray());
                    return(JavaScriptValue.Undefined);
                }
                catch (Exception e)
                {
                    return(JavaScriptValue.CreateError(JavaScriptValue.FromString(e.Message)));
                }
                finally
                {
                    Console.ForegroundColor = foreground;
                }
            }
            return(JavaScriptValue.CreateError(JavaScriptValue.FromString("Not enough arguments")));
        }
Exemplo n.º 12
0
 static JavaScriptValue NoConstructor(JavaScriptValue callee,
                                      [MarshalAs(UnmanagedType.U1)] bool isConstructCall,
                                      [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] JavaScriptValue[] arguments,
                                      ushort argumentCount,
                                      IntPtr callbackData)
 {
     try
     {
         var that = (TypeWrapper)GCHandle.FromIntPtr(callbackData).Target;
         if (that.type.IsValueType)
         {
             return(JSValue.FromObject(Activator.CreateInstance(that.type)).rawvalue);
         }
         else
         {
             Native.JsSetException(JavaScriptValue.CreateError(JavaScriptValue.FromString(that.type.Name + " has no constructor")));
             return(JavaScriptValue.Invalid);
         }
     }
     catch (Exception e)
     {
         return(ExceptionUtil.SetJSException(e));
     }
 }
Exemplo n.º 13
0
        /// <summary>
        ///     User implemented callback to fetch additional imported modules in ES modules.
        /// </summary>
        /// <remarks>
        ///     The callback is invoked on the current runtime execution thread, therefore execution is blocked until
        ///     the callback completes. Notify the host to fetch the dependent module. This is the "import" part
        ///     before HostResolveImportedModule in ES6 spec. This notifies the host that the referencing module has
        ///     the specified module dependency, and the host needs to retrieve the module back.
        ///
        ///     Callback should:
        ///     1. Check if the requested module has been requested before - if yes return the existing
        ///         module record
        ///     2. If no create and initialize a new module record with JsInitializeModuleRecord to
        ///         return and schedule a call to JsParseModuleSource for the new record.
        /// </remarks>
        /// <param name="referencingModule">The referencing module that is requesting the dependent module.</param>
        /// <param name="specifier">The specifier coming from the module source code.</param>
        /// <param name="dependentModuleRecord">The ModuleRecord of the dependent module. If the module was requested
        ///                                     before from other source, return the existing ModuleRecord, otherwise
        ///                                     return a newly created ModuleRecord.</param>
        /// <returns>
        ///     Returns a <c>JsNoError</c> if the operation succeeded an error code otherwise.
        /// </returns>
        /// <see cref="JavaScriptFetchImportedModuleCallBack"/>
        private JavaScriptErrorCode LoadModuleImpl(JavaScriptModuleRecord referencingModule, JavaScriptValue specifier, out JavaScriptModuleRecord dependentModuleRecord)
        {
            var specifierString = specifier.ToString();

            if (_moduleLeases.TryGetValue(specifierString, out var lease))
            {
                dependentModuleRecord = lease.Module;
                return(JavaScriptErrorCode.NoError);
            }

            var alias = ResourceModuleUtils.GetResourceAlias(specifierString);

            if (alias is null)
            {
                dependentModuleRecord           = JavaScriptModuleRecord.Initialize(referencingModule, specifier);
                dependentModuleRecord.HostUrl   = specifierString; // Only for debugging
                dependentModuleRecord.Exception = JavaScriptValue.CreateTypeError($"Failed to resolve module for specifier '{specifierString}'");
                _moduleLeases.Add(specifierString, new ModuleLease(dependentModuleRecord));
                dependentModuleRecord = _moduleLeases[specifierString].Module;
                return(JavaScriptErrorCode.NoError);
            }

            dependentModuleRecord         = JavaScriptModuleRecord.Initialize(referencingModule, specifier);
            dependentModuleRecord.HostUrl = specifierString; // Only for debugging
            _moduleLeases.Add(specifierString, new ModuleLease(dependentModuleRecord));

            // Fire off a task in the threadpool
            Task.Run(async() =>
            {
                var module = _moduleLeases[specifierString].Module;
                try
                {
                    var resource = await _resourceManager.GetResourceAsync(alias);

                    if (resource is object)
                    {
                        var script = _resourceScriptFactory.CreateFromExtension(resource, Path.GetExtension(specifierString));

                        _dispatcher.Invoke(() =>
                        {
                            using (_context.GetScope())
                            {
                                module.ParseSource(script);
                            }
                        });
                    }
                    else
                    {
                        _dispatcher.Invoke(() =>
                        {
                            using (_context.GetScope())
                            {
                                ThrowModuleException(module, JavaScriptValue.CreateError($"Could not find the resource '{specifierString}'"));
                            }
                        });
                    }
                }
                catch (Exception e)
                {
                    _dispatcher.Invoke(() =>
                    {
                        using (_context.GetScope())
                        {
                            ThrowModuleException(module, JavaScriptValue.CreateError(e.Message));
                        }
                    });
                }

                void ThrowModuleException(JavaScriptModuleRecord module, JavaScriptValue error)
                {
                    error.AddRef();
                    module.Exception = error;

                    if (!JavaScriptContext.HasException)
                    {
                        JavaScriptContext.SetException(error);
                    }

                    try
                    {
                        Native.ThrowIfError(JavaScriptErrorCode.ScriptException);
                    }
                    catch (Exception e)
                    {
                        OnResourceLoadError?.Invoke(e);
                    }
                    finally
                    {
                        error.Release();
                    }
                }
            });

            return(JavaScriptErrorCode.NoError);
        }
Exemplo n.º 14
0
 public static void ThrowError(string message)
 {
     JavaScriptContext.SetException(
         JavaScriptValue.CreateError(message)
         );
 }
Exemplo n.º 15
0
        /// <summary>
        /// This method will set a javascript exception on the current context.
        /// </summary>
        /// <param name="message">The message to use in the exception.</param>
        public static void SetJsException(string message)
        {
            var error = JavaScriptValue.CreateError(JavaScriptValue.FromString(message));

            JavaScriptContext.SetException(error);
        }