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); } }
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); }
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); }
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); }
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 }
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"))); }
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); }
/// <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"))); }
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)); } }
/// <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); }
public static void ThrowError(string message) { JavaScriptContext.SetException( JavaScriptValue.CreateError(message) ); }
/// <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); }