public async Task ReactBridge_InvokeCallback() { await JavaScriptHelpers.Run(async (executor, jsQueueThread) => { using (var nativeThread = new ActionQueue(ex => { Assert.Fail(); })) { var bridge = new ReactBridge(executor, new MockReactCallback(), nativeThread); var token = await jsQueueThread.RunAsync(() => { bridge.InvokeCallback(1, new JArray()); return(executor.GetGlobalVariable("CallbackCalls")); }); var expected = new JArray { new JArray { 1, new JArray(), }, }; Assert.That(expected.ToString(Formatting.None), Is.EqualTo(token.ToString(Formatting.None))); } }); }
public async Task ReactBridge_CallFunction() { await JavaScriptHelpers.Run(async (executor, jsQueueThread) => { using (var nativeThread = CreateNativeModulesThread()) { var reactCallback = new MockReactCallback(); var bridge = new ReactBridge(executor, new MockReactCallback(), nativeThread); var token = await jsQueueThread.CallOnQueue(() => { bridge.CallFunction("module", "method", new JArray()); return(executor.GetGlobalVariable("FunctionCalls")); }); var expected = new JArray { new JArray { "module", "method", new JArray(), }, }; Assert.AreEqual(expected.ToString(Formatting.None), token.ToString(Formatting.None)); } }); }
public async Task ChakraJavaScriptExecutor_ArgumentChecks() { await JavaScriptHelpers.Run((executor, jsQueueThread) => { AssertEx.Throws <ArgumentNullException>( () => executor.Call(null, "foo", new JArray()), ex => Assert.AreEqual("moduleName", ex.ParamName)); AssertEx.Throws <ArgumentNullException>( () => executor.Call("foo", null, new JArray()), ex => Assert.AreEqual("methodName", ex.ParamName)); AssertEx.Throws <ArgumentNullException>( () => executor.Call("foo", "bar", null), ex => Assert.AreEqual("arguments", ex.ParamName)); AssertEx.Throws <ArgumentNullException>( () => executor.RunScript(null), ex => Assert.AreEqual("script", ex.ParamName)); AssertEx.Throws <ArgumentNullException>( () => executor.SetGlobalVariable(null, new JArray()), ex => Assert.AreEqual("propertyName", ex.ParamName)); AssertEx.Throws <ArgumentNullException>( () => executor.SetGlobalVariable("foo", null), ex => Assert.AreEqual("value", ex.ParamName)); AssertEx.Throws <ArgumentNullException>( () => executor.GetGlobalVariable(null), ex => Assert.AreEqual("propertyName", ex.ParamName)); }); }
public async Task ReactBridge_InvokeCallback() { await JavaScriptHelpers.Run(async (executor, jsQueueThread) => { using (var nativeThread = MessageQueueThread.Create(MessageQueueThreadSpec.Create("native", MessageQueueThreadKind.BackgroundAnyThread), ex => { Assert.Fail(); })) { var reactCallback = new MockReactCallback(); var bridge = new ReactBridge(executor, new MockReactCallback(), nativeThread); var token = await jsQueueThread.CallOnQueue(() => { bridge.InvokeCallback(1, new JArray()); return(executor.GetGlobalVariable("CallbackCalls")); }); var expected = new JArray { new JArray { 1, new JArray(), }, }; Assert.AreEqual(expected.ToString(Formatting.None), token.ToString(Formatting.None)); } }); }
public async Task ReactBridge_Ctor_ArgumentChecks() { await JavaScriptHelpers.Run((executor, jsQueueThread) => { using (var nativeThread = CreateNativeModulesThread()) { var reactCallback = new MockReactCallback(); Assert.That( () => new ReactBridge(null, reactCallback, nativeThread), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("executor") ); Assert.That( () => new ReactBridge(executor, null, nativeThread), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("reactCallback") ); Assert.That( () => new ReactBridge(executor, reactCallback, null), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("nativeModulesQueueThread") ); } }); }
/// <summary> /// Setup RequireJS to be used in layouts /// </summary> /// <param name="html"> /// Html helper. /// </param> /// <param name="config"> /// Configuration object for various options. /// </param> /// <returns> /// The <see cref="MvcHtmlString"/>. /// </returns> public static MvcHtmlString RenderRequireJsSetup( this HtmlHelper html, RequireRendererConfiguration config) { if (config == null) { throw new ArgumentNullException("config"); } var entryPointPath = html.RequireJsEntryPoint(config.BaseUrl, config.EntryPointRoot); if (entryPointPath == null) { return(new MvcHtmlString(string.Empty)); } if (config.ConfigurationFiles == null || !config.ConfigurationFiles.Any()) { throw new Exception("No config files to load."); } var processedConfigs = config.ConfigurationFiles.Select(r => { var resultingPath = html.ViewContext.HttpContext.MapPath(r); PathHelpers.VerifyFileExists(resultingPath); return(resultingPath); }).ToList(); var resultingConfig = GetCachedOverridenConfig(processedConfigs, config, entryPointPath.ToString()); var locale = config.LocaleSelector(html); var outputConfig = createOutputConfigFrom(resultingConfig, config, locale); var options = createOptionsFrom(html.ViewContext.HttpContext, config, locale); var configBuilder = new JavaScriptBuilder(); configBuilder.AddStatement(JavaScriptHelpers.SerializeAsVariable(options, "requireConfig")); configBuilder.AddStatement(JavaScriptHelpers.SerializeAsVariable(outputConfig, "require")); var requireRootBuilder = new JavaScriptBuilder(); requireRootBuilder.AddAttributesToStatement("src", config.RequireJsUrl); var requireEntryPointBuilder = new JavaScriptBuilder(); requireEntryPointBuilder.AddStatement( JavaScriptHelpers.MethodCall( "require", (object)new[] { entryPointPath.ToString() })); return(new MvcHtmlString( configBuilder.Render() + Environment.NewLine + requireRootBuilder.Render() + Environment.NewLine + requireEntryPointBuilder.Render())); }
public void Truthiness() { Assert.IsFalse(JavaScriptHelpers.IsTruthy(null), "Null is not truthy."); Assert.IsTrue(JavaScriptHelpers.IsTruthy(this), "Non-null object is truthy."); Assert.IsTrue(JavaScriptHelpers.IsTruthy(true), "Boolean value of true is truthy."); Assert.IsFalse(JavaScriptHelpers.IsTruthy(false), "Boolean value of false is not truthy."); Assert.IsTrue(JavaScriptHelpers.IsTruthy((sbyte)42), "Non-zero sbyte value is truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((sbyte)-42), "Non-zero sbyte value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((sbyte)0), "Zero sbyte value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((byte)42), "Non-zero byte value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((byte)0), "Zero byte value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((char)0), "Char value is truthy."); Assert.IsTrue(JavaScriptHelpers.IsTruthy((short)42), "Non-zero short value is truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((short)-42), "Non-zero short value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((short)0), "Zero short value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((ushort)42), "Non-zero ushort value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((ushort)0), "Zero ushort value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((int)42), "Non-zero int value is truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((int)-42), "Non-zero int value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((int)0), "Zero int value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((uint)42), "Non-zero uint value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((uint)0), "Zero uint value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((long)42), "Non-zero long value is truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((long)-42), "Non-zero long value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((long)0), "Zero long value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((ulong)42), "Non-zero ulong value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((ulong)0), "Zero ulong value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((float)42), "Non-zero float value is truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((float)-42), "Non-zero float value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((float)0), "Zero float value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((double)42), "Non-zero double value is truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((double)-42), "Non-zero double value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((double)0), "Zero double value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((decimal)42), "Non-zero decimal value is truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((decimal) - 42), "Non-zero decimal value is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy((decimal)0), "Zero decimal value is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy("42"), "Non-zero length string is truthy"); Assert.IsFalse(JavaScriptHelpers.IsTruthy(""), "Zero length string is not truthy"); Assert.IsTrue(JavaScriptHelpers.IsTruthy((bool?)true), "Nullable values' truthiness is based on the actual value if they do not have a value assigned."); Assert.IsFalse(JavaScriptHelpers.IsTruthy((bool?)false), "Nullable values' truthiness is based on the actual value if they do not have a value assigned."); Assert.IsFalse(JavaScriptHelpers.IsTruthy((char?)null), "Nullable values are not truthy if they do not have a value assigned."); }
/// <summary> /// Setup RequireJS to be used in layouts /// </summary> /// <param name="baseUrl">Scrips folder</param> /// <param name="requireUrl">requirejs.js url</param> /// <param name="configsList">RequireJS.config files path</param> public static MvcHtmlString RenderRequireJsSetup(this HtmlHelper html, string baseUrl, string requireUrl, IList <string> configsList, IRequireJsLogger logger = null) { var entryPointPath = html.RequireJsEntryPoint(); if (entryPointPath == null) { return(new MvcHtmlString(string.Empty)); } if (!configsList.Any()) { throw new Exception("No config files to load."); } var processedConfigs = configsList.Select(r => { var resultingPath = html.ViewContext.HttpContext.MapPath(r); PathHelpers.VerifyFileExists(resultingPath); return(resultingPath); }).ToList(); var loader = new ConfigLoader(processedConfigs, logger); var resultingConfig = loader.Get(); var outputConfig = new JsonConfig { BaseUrl = baseUrl, Locale = html.CurrentCulture(), Paths = resultingConfig.Paths.PathList.ToDictionary(r => r.Key, r => r.Value), Shim = resultingConfig.Shim.ShimEntries.ToDictionary(r => r.For, r => new JsonRequireDeps { Dependencies = r.Dependencies.Select(x => x.Dependency).ToList(), Exports = r.Exports }), Map = resultingConfig.Map.MapElements.ToDictionary(r => r.For, r => r.Replacements.ToDictionary(x => x.OldKey, x => x.NewKey)) }; var options = new JsonRequireOptions { Locale = html.CurrentCulture(), PageOptions = html.ViewBag.PageOptions, WebsiteOptions = html.ViewBag.GlobalOptions }; var configBuilder = new JavaScriptBuilder(); configBuilder.AddStatement(JavaScriptHelpers.SerializeAsVariable(options, "requireConfig")); configBuilder.AddStatement(JavaScriptHelpers.SerializeAsVariable(outputConfig, "require")); var requireRootBuilder = new JavaScriptBuilder(); requireRootBuilder.AddAttributesToStatement("data-main", entryPointPath.ToString()); requireRootBuilder.AddAttributesToStatement("src", requireUrl); return(new MvcHtmlString(configBuilder.Render() + requireRootBuilder.Render())); }
// Implement ICanCreateJsonFields public virtual void AddJsonFields(IList <string> jsonFields, Dictionary <string, string> appenderNames, Func <string, string> virtualToAbsoluteFunc) { var stringValue = new StringValue(); JavaScriptHelpers.AddJsonField(jsonFields, FieldLevel, level, new LevelValue()); JavaScriptHelpers.AddJsonField(jsonFields, "ipRegex", ipRegex, stringValue); JavaScriptHelpers.AddJsonField(jsonFields, "userAgentRegex", userAgentRegex, stringValue); JavaScriptHelpers.AddJsonField(jsonFields, "disallow", disallow, stringValue); }
// Implement ICanCreateJsonFields public override void AddJsonFields(IList <string> jsonFields, Dictionary <string, string> appenderNames, Func <string, string> virtualToAbsoluteFunc) { var levelValue = new LevelValue(); JavaScriptHelpers.AddJsonField(jsonFields, FieldSendWithBufferLevel, sendWithBufferLevel, levelValue); JavaScriptHelpers.AddJsonField(jsonFields, FieldStoreInBufferLevel, storeInBufferLevel, levelValue); JavaScriptHelpers.AddJsonField(jsonFields, FieldBufferSize, bufferSize); JavaScriptHelpers.AddJsonField(jsonFields, FieldBatchSize, batchSize); base.AddJsonFields(jsonFields, appenderNames, virtualToAbsoluteFunc); }
public async Task ThrowsWithCorrectParameterNameWhenGivenNull() { await JavaScriptHelpers.Run((executor, jsQueueThread) => { Assert.That( () => executor.CallFunctionReturnFlushedQueue(null, "foo", new JArray()), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("moduleName") ); Assert.That( () => executor.CallFunctionReturnFlushedQueue("foo", null, new JArray()), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("methodName") ); Assert.That( () => executor.CallFunctionReturnFlushedQueue("foo", "bar", null), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("arguments") ); Assert.That( () => executor.InvokeCallbackAndReturnFlushedQueue(0, null), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("arguments") ); Assert.That( () => executor.RunScript(null, "foo"), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("sourcePath") ); Assert.That( () => executor.RunScript("", null), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("sourceUrl") ); Assert.That( () => executor.SetGlobalVariable(null, new JArray()), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("propertyName") ); Assert.That( () => executor.SetGlobalVariable("foo", null), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("value") ); Assert.That( () => executor.GetGlobalVariable(null), Throws.ArgumentNullException.With.Property("ParamName").EqualTo("propertyName") ); }); }
// Implement ICanCreateJsonFields public void AddJsonFields(IList <string> jsonFields, Dictionary <string, string> appenderNames, Func <string, string> virtualToAbsoluteFunc) { try { JavaScriptHelpers.AddJsonField(jsonFields, FieldEnabled, enabled); JavaScriptHelpers.AddJsonField(jsonFields, FieldMaxMessages, maxMessages); JavaScriptHelpers.AddJsonField(jsonFields, FieldDefaultAjaxUrl, defaultAjaxUrl, new UrlValue(virtualToAbsoluteFunc)); } catch (Exception e) { string displayName = "jsnlog library"; throw new ConfigurationException(displayName, e); } }
public void ParseConstant() { object result; JavaScriptHelpers.ParseConstant("'this'").Should().Be("this"); JavaScriptHelpers.ParseConstant("5").Should().Be(5); JavaScriptHelpers.ParseConstant("0.25").Should().Be(0.25); JavaScriptHelpers.ParseConstant("true").Should().Be(true); JavaScriptHelpers.ParseConstant("false").Should().Be(false); JavaScriptHelpers.TryParseConstant("0.25", out result).Should().Be(true); JavaScriptHelpers.TryParseConstant("false", out result).Should().Be(true); JavaScriptHelpers.TryParseConstant("xi0", out result).Should().Be(false); JavaScriptHelpers.TryParseConstant("'unbalanced", out result).Should().Be(false); }
// Implement ICanCreateJsonFields public override void AddJsonFields(IList <string> jsonFields, Dictionary <string, string> appenderNames, Func <string, string> virtualToAbsoluteFunc) { JavaScriptHelpers.AddJsonField(jsonFields, FieldAppenders, appenders, new AppendersValue(appenderNames)); if (onceOnlies != null) { // Note that regex on a onceOnly object can be null (that is, not given in the config). // This allows user to specify an empty list of onceOnlies, to override the onceOnlies of // the parent logger. See http://jsnlog.com/Documentation/WebConfig/JSNLog/Logger JavaScriptHelpers.AddJsonField(jsonFields, FieldOnceOnly, onceOnlies.Select(o => o.regex), new StringValue()); } base.AddJsonFields(jsonFields, appenderNames, virtualToAbsoluteFunc); }
public async Task ReactBridge_Method_ArgumentChecks() { await JavaScriptHelpers.Run((executor, jsQueueThread) => { using (var nativeThread = CreateNativeModulesThread()) { var reactCallback = new MockReactCallback(); var bridge = new ReactBridge(executor, reactCallback, nativeThread); AssertEx.Throws <ArgumentNullException>( () => bridge.SetGlobalVariable(null, null), ex => Assert.AreEqual("propertyName", ex.ParamName)); } }); }
public void Abort(System.IO.TextWriter writer, bool isHtmlBool) { // Bound attribute if (binding != null) { RenderAttribute(writer, attribute.Name, attribute.Binding.Expression); } // Simple attribute else if (!isHtmlBool) { RenderAttribute(writer, attribute.Name, attribute.Value); } else if (JavaScriptHelpers.IsTruthy(attribute.Value)) { RenderAttribute(writer, attribute.Name, attribute.Name); } }
// Implement ICanCreateElement public void CreateElement(StringBuilder sb, Dictionary <string, string> appenderNames, int sequence, Func <string, string> virtualToAbsoluteFunc) { try { string jsVariableName = string.Format("{0}{1}", Constants.JsLoggerVariablePrefix, sequence); JavaScriptHelpers.GenerateLogger(jsVariableName, name, sb); JavaScriptHelpers.GenerateSetOptions(jsVariableName, this, appenderNames, virtualToAbsoluteFunc, sb, null); } catch (Exception e) { string displayName = String.IsNullOrEmpty(name) ? "<nameless root logger>" : name;; throw new ConfigurationException(displayName, e); } }
public async Task ReactBridge_SyncCallback() { var jsFactories = new Func <IJavaScriptExecutor>[] { () => new ChakraJavaScriptExecutor(), #if WINDOWS_UWP () => new NativeJavaScriptExecutor(), #endif }; foreach (var jsFactory in jsFactories) { await JavaScriptHelpers.Run(async (executor, jsQueueThread) => { using (var nativeThread = CreateNativeModulesThread()) { var moduleId = 42; var methodId = 7; var called = 0; var callback = new MockReactCallback { InvokeSyncHandler = (mod, met, arg) => { Assert.AreEqual(moduleId, mod); Assert.AreEqual(methodId, met); Assert.AreEqual(0, arg.Count); ++called; return(JValue.CreateNull()); }, }; var bridge = new ReactBridge(executor, callback, nativeThread); await jsQueueThread.RunAsync(() => { bridge.CallFunction("SyncModule", "test", new JArray { 42, 7, new JArray() }); }); Assert.AreEqual(1, called); } }, jsFactory, @"Resources/sync.js"); } }
protected bool TryRenderIf(AjaxPage page, IEnumerable <string> templateNames, System.IO.TextWriter writer, out AttributeBinding ifBinding, out bool canRender) { if (If == null) { ifBinding = null; canRender = true; return(true); } ifBinding = If.Evaluate(page); if (!ifBinding.IsValid) { canRender = false; return(false); } canRender = JavaScriptHelpers.IsTruthy(ifBinding.Value); return(true); }
protected void CreateAppender(StringBuilder sb, Dictionary <string, string> appenderNames, int sequence, Func <string, string> virtualToAbsoluteFunc, string jsCreateMethodName, string configurationObjectName) { try { ValidateAppender(configurationObjectName); string appenderVariableName = string.Format("{0}{1}", Constants.JsAppenderVariablePrefix, sequence); appenderNames[name] = appenderVariableName; JavaScriptHelpers.GenerateCreate(appenderVariableName, jsCreateMethodName, name, sb); JavaScriptHelpers.GenerateSetOptions(appenderVariableName, this, appenderNames, virtualToAbsoluteFunc, sb, null); } catch (Exception e) { throw new ConfigurationException(name, e); } }
public async Task ReactBridge_Ctor_ArgumentChecks() { await JavaScriptHelpers.Run((executor, jsQueueThread) => { using (var nativeThread = CreateNativeModulesThread()) { var reactCallback = new MockReactCallback(); AssertEx.Throws <ArgumentNullException>( () => new ReactBridge(null, reactCallback, nativeThread), ex => Assert.AreEqual("executor", ex.ParamName)); AssertEx.Throws <ArgumentNullException>( () => new ReactBridge(executor, null, nativeThread), ex => Assert.AreEqual("reactCallback", ex.ParamName)); AssertEx.Throws <ArgumentNullException>( () => new ReactBridge(executor, reactCallback, null), ex => Assert.AreEqual("nativeModulesQueueThread", ex.ParamName)); } }); }
// -------------------------------- public void ProcessLogger(XmlElement xe, string parentName, Dictionary <string, string> appenderNames, Sequence sequence, IEnumerable <AttributeInfo> loggerAttributes, StringBuilder sb) { if (xe == null) { return; } var appendersValue = new AppendersValue(appenderNames); string appenders = XmlHelpers.OptionalAttribute(xe, "appenders", null, appendersValue.ValidValueRegex); string loggerName = XmlHelpers.OptionalAttribute(xe, "name", ""); JavaScriptHelpers.GenerateLogger(Constants.JsLoggerVariable, loggerName, sb); AttributeValueCollection attributeValues = new AttributeValueCollection(); if (appenders != null) { attributeValues[Constants.JsLoggerAppendersOption] = new Value(appenders, appendersValue); } Utils.ProcessOptionAttributes(Constants.JsLoggerVariable, xe, loggerAttributes, attributeValues, sb); }
protected void ProcessAppender(XmlElement xe, string parentName, Dictionary <string, string> appenderNames, Sequence sequence, IEnumerable <AttributeInfo> appenderAttributes, string jsCreateMethodName, List <XmlHelpers.TagInfo> childTagInfos, StringBuilder sb) { if (xe == null) { return; } string appenderName = XmlHelpers.RequiredAttribute(xe, "name"); string appenderVariableName = string.Format("{0}{1}", Constants.JsAppenderVariablePrefix, sequence.Next()); appenderNames[appenderName] = appenderVariableName; JavaScriptHelpers.GenerateCreate(appenderVariableName, jsCreateMethodName, appenderName, sb); Utils.ProcessOptionAttributes( appenderVariableName, xe, appenderAttributes, null, sb, (attributeValues) => { Validate(appenderName, attributeValues); }); XmlHelpers.ProcessNodeList( xe.ChildNodes, childTagInfos, appenderVariableName, appenderNames, sequence, sb); }
public void Render(AjaxPage page, System.IO.TextWriter writer, bool isHtmlBool, bool generateIds, bool isTextArea) { // Bound attribute if (binding != null) { // Valid binding if (binding.IsValid) { // Render the binding value for sys attributes if (attribute.Name.StartsWith("sys:")) { var attributeName = attribute.Name.Substring(4); // Render two-way binding expressions if (attribute.Binding.IsTwoWay) { RenderAttribute(writer, "data-sys-" + attributeName, attribute.Binding.Expression); } if (binding.Value != null) { if (attributeName != "if" && attributeName != "innerhtml" && attributeName != "innertext" && !(isTextArea && attributeName == "value") && !attribute.Name.StartsWith("sys:class-")) { if (isHtmlBool) { if (JavaScriptHelpers.IsTruthy(binding.Value)) { RenderAttribute(writer, attributeName, attributeName); } } else { RenderAttribute(writer, attributeName, binding.Value.ToString()); } } } } else { RenderAttribute(writer, "data-" + attribute.Name.Replace(':', '-'), attribute.Binding.Expression); } } // Invalid binding else { RenderAttribute(writer, attribute.Name, attribute.Binding.Expression); } } else if (generateIds && (attribute.Name == "id" || attribute.Name == "sys:id")) { RenderAttribute(writer, "id", page.Context.GetInstanceId(attribute.Value)); } // Simple attribute else if (attribute.Name.Contains(":") && attribute.Name != "sys:id") { RenderAttribute(writer, "data-" + attribute.Name.Replace(':', '-'), attribute.Value); } else if (isHtmlBool) { if (JavaScriptHelpers.IsTruthy(attribute.Value)) { RenderAttribute(writer, attribute.Name, attribute.Name); } } else { RenderAttribute(writer, attribute.Name, attribute.Value); } }
// Implement ICanCreateJsonFields public override void AddJsonFields(IList <string> jsonFields, Dictionary <string, string> appenderNames, Func <string, string> virtualToAbsoluteFunc) { JavaScriptHelpers.AddJsonField(jsonFields, FieldUrl, url, new UrlValue(virtualToAbsoluteFunc)); base.AddJsonFields(jsonFields, appenderNames, virtualToAbsoluteFunc); }
protected void RenderStartTag(AjaxPage page, System.IO.TextWriter writer, Func <IEnumerable <AttributeBinding>, IEnumerable <AttributeBinding> > attributeTransform, bool abort, params AttributeBinding[] bindings) { // Immediately abort if no tag name if (Tag == null) { return; } // Open Tag writer.Write("<" + Tag); // Attributes string innerContent = null; var attributes = (Attributes ?? new List <Attribute>()) .Select(attribute => attribute.Binding == null ? new AttributeBinding(attribute, null) : attribute.Binding.Evaluate(page)); // Adding binding attributes if necessary if (bindings != null && bindings.Length > 0) { attributes = attributes.Concat(bindings.Where(b => b != null)); } // Transform the attributes if necessary if (attributeTransform != null) { attributes = attributeTransform(attributes); } string classNames = null; bool foundId = false; bool isTextArea = Tag.Equals("textarea", StringComparison.InvariantCultureIgnoreCase); var attrs = attributes.ToArray(); // Write the attributes to the output stream foreach (var attribute in attrs) { // Ensure that multiple id attributes are not specified if (!page.Context.IsGlobal && (attribute.Name == "id" || attribute.Name == "sys:id")) { if (foundId) { throw new ApplicationException("Found multiple id attributes: " + Markup); } foundId = true; } // Determine if the attribute represents bound element content if (attribute.IsBound) { if (attribute.Name == "sys:innerhtml" || (isTextArea && attribute.Name == "sys:value")) { innerContent = (attribute.DisplayValue ?? ""); } else if (attribute.Name == "sys:innertext") { innerContent = HttpUtility.HtmlEncode(attribute.DisplayValue ?? ""); } } bool isHtmlBoolean; var attributeName = attribute.Name.StartsWith("sys:") ? attribute.Name.Substring(4) : attribute.Name; if (Tag.Equals("input", StringComparison.InvariantCultureIgnoreCase)) { var attr = attrs.SingleOrDefault(a => a.Name.Equals("type", StringComparison.InvariantCultureIgnoreCase) && a.IsValid && a.Value != null); if (attr == null) { isHtmlBoolean = HtmlHelpers.IsBooleanAttribute(attributeName, Tag, null, true); } else { isHtmlBoolean = HtmlHelpers.IsBooleanAttribute(attributeName, Tag, attr.Value.ToString()); } } else { isHtmlBoolean = HtmlHelpers.IsBooleanAttribute(attributeName, Tag); } if (abort) { attribute.Abort(writer, isHtmlBoolean); } else { if (attribute.Name == "class") { if (classNames == null) { classNames = (string)attribute.Value; } else { classNames += " " + (string)attribute.Value; } } else { if (attribute.Name.StartsWith("sys:class-")) { // If binding evaluates as truthy, then render the store the class name if (JavaScriptHelpers.IsTruthy(attribute.Value)) { string sysClassValue = attribute.Name.Substring(10); if (classNames == null) { classNames = sysClassValue; } else { classNames += (classNames.Length > 0 ? " " : "") + sysClassValue; } } } attribute.Render(page, writer, isHtmlBoolean, !page.Context.IsGlobal, isTextArea); } } } // Write direct class and sys:class- attribute values together. Note: by checking // for null we may be avoiding writing a class attribute altogether whereas the // client framework would have produced an empty class attribute. if (classNames != null) { writer.Write(" class=\""); HttpUtility.HtmlAttributeEncode(classNames, writer); writer.Write("\""); } // Close Tag if (IsEmpty) { if (!string.IsNullOrEmpty(innerContent)) { writer.Write(">" + innerContent + "</" + Tag + ">"); } else if (HtmlHelpers.IsSelfClosing(Tag)) { writer.Write(" />"); } else { writer.Write("></" + Tag + ">"); } } else if (!string.IsNullOrEmpty(innerContent)) { writer.Write(">" + innerContent); } else { writer.Write(">"); } }
public async Task ReactBridge_FlushQueueImmediate() { var jsFactories = new Func <IJavaScriptExecutor>[] { () => new ChakraJavaScriptExecutor(), #if WINDOWS_UWP () => new NativeJavaScriptExecutor(), #endif }; foreach (var jsFactory in jsFactories) { await JavaScriptHelpers.Run(async (executor, jsQueueThread) => { using (var nativeThread = CreateNativeModulesThread()) { var moduleId = 42; var methodId = 7; var called = 0; var countdownEvent = new CountdownEvent(1); var callback = new MockReactCallback { InvokeHandler = (mod, met, arg) => { Assert.AreEqual(moduleId, mod); Assert.AreEqual(methodId, met); Assert.AreEqual(1, arg.Count); Assert.AreEqual("foo", arg[0].Value <string>()); ++called; }, OnBatchCompleteHandler = () => countdownEvent.Signal(), }; var bridge = new ReactBridge(executor, callback, nativeThread); await jsQueueThread.RunAsync(() => { bridge.CallFunction("FlushQueueImmediateModule", "test", new JArray { 10, new JArray { new JArray { 42 }, new JArray { 7 }, new JArray { new JArray { "foo" } } } }); }); // wait for `OnBatchComplete` in background // so we don't block native module thread await Task.Run(new Action(countdownEvent.Wait)); Assert.AreEqual(10, called); } }, jsFactory, @"Resources/immediate.js"); } }
/// <summary> /// Setup RequireJS to be used in layouts /// </summary> /// <param name="html"> /// Html helper. /// </param> /// <param name="config"> /// Configuration object for various options. /// </param> /// <returns> /// The <see cref="MvcHtmlString"/>. /// </returns> public static MvcHtmlString RenderRequireJsSetup( this HtmlHelper html, RequireRendererConfiguration config) { if (config == null) { throw new ArgumentNullException("config"); } var entryPointPath = html.RequireJsEntryPoint(config.BaseUrl, config.EntryPointRoot); if (entryPointPath == null) { return(new MvcHtmlString(string.Empty)); } if (config.ConfigurationFiles == null || !config.ConfigurationFiles.Any()) { throw new Exception("No config files to load."); } var processedConfigs = config.ConfigurationFiles.Select(r => { var resultingPath = html.ViewContext.HttpContext.MapPath(r); PathHelpers.VerifyFileExists(resultingPath); return(resultingPath); }).ToList(); var resultingConfig = GetCachedOverridenConfig(processedConfigs, config, entryPointPath.ToString()); var locale = config.LocaleSelector(html); var outputConfig = new JsonRequireOutput { BaseUrl = config.BaseUrl, Locale = locale, UrlArgs = config.UrlArgs, WaitSeconds = config.WaitSeconds, Paths = resultingConfig.Paths.PathList.ToDictionary(r => r.Key, r => r.Value), Shim = resultingConfig.Shim.ShimEntries.ToDictionary( r => r.For, r => new JsonRequireDeps { Dependencies = r.Dependencies.Select(x => x.Dependency).ToList(), Exports = r.Exports }), Map = resultingConfig.Map.MapElements.ToDictionary( r => r.For, r => r.Replacements.ToDictionary(x => x.OldKey, x => x.NewKey)) }; config.ProcessConfig(outputConfig); var options = new JsonRequireOptions { Locale = locale, PageOptions = RequireJsOptions.GetPageOptions(html.ViewContext.HttpContext), WebsiteOptions = RequireJsOptions.GetGlobalOptions(html.ViewContext.HttpContext) }; config.ProcessOptions(options); var configBuilder = new JavaScriptBuilder(); configBuilder.AddStatement(JavaScriptHelpers.SerializeAsVariable(options, "requireConfig")); configBuilder.AddStatement(JavaScriptHelpers.SerializeAsVariable(outputConfig, "require")); var requireRootBuilder = new JavaScriptBuilder(); requireRootBuilder.AddAttributesToStatement("src", config.RequireJsUrl); var requireEntryPointBuilder = new JavaScriptBuilder(); requireEntryPointBuilder.AddStatement( JavaScriptHelpers.MethodCall( "require", (object)new[] { entryPointPath.ToString() })); return(new MvcHtmlString( configBuilder.Render() + Environment.NewLine + requireRootBuilder.Render() + Environment.NewLine + requireEntryPointBuilder.Render())); }
internal override void Render(AjaxPage page, string[] templateNames, System.IO.TextWriter writer) { bool canRender; AttributeBinding ifBinding; if (!TryRenderIf(page, templateNames, writer, out ifBinding, out canRender)) { Abort(page, templateNames, writer); return; } if (!canRender) { return; } // Output the original template if toggle on was not specified if (On == null) { Abort(page, templateNames, writer); return; } // Get the data associated with the data view var onBinding = On.Evaluate(page); // Output the original template if no data for on was found if (!onBinding.IsValid) { Abort(page, templateNames, writer); return; } var onValue = onBinding.Value; var classValue = ""; var classBinding = (AttributeBinding)null; if (ClassName != null) { classBinding = ClassName.Evaluate(page); // Output the original template if no data for class was found if (!classBinding.IsValid) { Abort(page, templateNames, writer); return; } classValue = (string)classBinding.Value; } ToggleAction?actionValue; var actionBinding = (AttributeBinding)null; // Get the value of the toggle action (i.e.: show, hide, etc.) if (Action != null) { actionBinding = Action.Evaluate(page); // Output the original template if no data for action was found if (!actionBinding.IsValid) { Abort(page, templateNames, writer); return; } actionValue = (ToggleAction)Enum.Parse(typeof(ToggleAction), (string)actionBinding.Value, true); } else if (!string.IsNullOrEmpty(classValue)) { actionValue = ToggleAction.AddClass; } else { actionValue = ToggleAction.Show; } var groupNameBinding = (AttributeBinding)null; if (GroupName != null) { groupNameBinding = GroupName.Evaluate(page); // Output the original template if no data for group name was found if (!groupNameBinding.IsValid) { Abort(page, templateNames, writer); return; } } var strictModeValue = false; var strictModeBinding = (AttributeBinding)null; if (StrictMode != null) { strictModeBinding = StrictMode.Evaluate(page); // Output the original template if no data for strict mode was found if (!strictModeBinding.IsValid) { Abort(page, templateNames, writer); return; } if (strictModeBinding.Value is bool) { strictModeValue = (bool)strictModeBinding.Value; } else { strictModeValue = bool.Parse((string)strictModeBinding.Value); } } bool?equals; var whenBinding = (AttributeBinding)null; // Evaluate whether the on and when conditions are equal or // satisified, which determines whether the toggle is on or off if (When == null) { if (strictModeValue) { // In strict mode the on value must be a boolean true if (!(onValue is bool)) { throw new ApplicationException(string.Format("With strict mode enabled, toggle:on should be a value of type Boolean, actual type \"{0}\".", onValue == null ? "null" : onValue.GetType().Name)); } equals = (bool)onValue; } else if (onValue is System.Collections.IEnumerable) { equals = false; // Satisfied if there are any items foreach (object o in (System.Collections.IEnumerable)onValue) { equals = true; break; } } else { // Otherwise, check to see that the on value is "truthy" equals = JavaScriptHelpers.IsTruthy(onValue); } } else { whenBinding = When.Evaluate(page); var whenValue = whenBinding.Value; if (whenValue == null) { equals = (onValue == null); } else if (whenValue is FunctionInstance) { object result; try { result = Page.ScriptMarshaller.Unwrap(((FunctionInstance)whenValue).Call(null, Page.ScriptMarshaller.Wrap(onValue))); } catch { Abort(page, templateNames, writer); return; } if (strictModeValue) { if (!(result is bool)) { throw new ApplicationException(string.Format("With strict mode enabled, toggle:when function should return a value of type Boolean, found type \"{0}\".", result == null ? "null" : result.GetType().Name)); } equals = (bool)result; } else { equals = JavaScriptHelpers.IsTruthy(result); } } else { equals = whenValue.Equals(onValue); } } // If no class value is defined then abort if ((actionValue == ToggleAction.AddClass || actionValue == ToggleAction.RemoveClass) && string.IsNullOrEmpty(classValue)) { Abort(page, templateNames, writer); return; } bool render = actionValue == ToggleAction.Render || actionValue == ToggleAction.Dispose; AttributeBinding contentTemplateBinding; if (!TryContentTemplate(page, templateNames, writer, out contentTemplateBinding)) { Abort(page, templateNames, writer); return; } var ownTemplateNames = contentTemplateBinding != null ? ((string)contentTemplateBinding.Value).Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) : new string[0]; using (var context = render ? page.BeginContext(page.Context.DataItem, null) : null) { RenderStartTag(page, writer, attrs => MergeAttribute(MergeAttribute(MergeAttribute(attrs, "class", value => { if (actionValue == ToggleAction.AddClass || actionValue == ToggleAction.RemoveClass) { if ((actionValue == ToggleAction.AddClass && equals.Value) || (actionValue == ToggleAction.RemoveClass && !equals.Value)) { value = AttributeHelper.EnsureClassName(value, classValue); } else { value = AttributeHelper.RemoveClassName(value, classValue); } } // Add/remove the "toggle-on" and "toggle-off" classes based on state value = AttributeHelper.EnsureClassName(value, equals.Value ? "toggle-on" : "toggle-off"); value = AttributeHelper.RemoveClassName(value, equals.Value ? "toggle-off" : "toggle-on"); return(value); }).ToArray(), "style", value => { if (actionValue == ToggleAction.Show || actionValue == ToggleAction.Hide || actionValue == ToggleAction.Render || actionValue == ToggleAction.Dispose) { if (((actionValue == ToggleAction.Show || actionValue == ToggleAction.Render) && equals.Value) || ((actionValue == ToggleAction.Hide || actionValue == ToggleAction.Dispose) && !equals.Value)) { if (AttributeHelper.GetCssStyle(value, "display") == "none") { value = AttributeHelper.RemoveCssStyle(value, "display"); } } else { value = AttributeHelper.EnsureCssStyle(value, "display", "none"); } } return(value); }).ToArray(), "disabled", value => { if (actionValue == ToggleAction.Enable || actionValue == ToggleAction.Disable) { if ((actionValue == ToggleAction.Enable && equals.Value) || (actionValue == ToggleAction.Disable && !equals.Value)) { value = null; } else { value = "disabled"; } } return(value); }), ifBinding, onBinding, classBinding, actionBinding, groupNameBinding, strictModeBinding, whenBinding, contentTemplateBinding, // If this is render/dispose, include the nested template index as a special attribute render ? new AttributeBinding(new Attribute() { Name = "data-sys-tmplidx", Value = NestedTemplateIndex.ToString() }, null) : null, render ? new AttributeBinding(new Attribute() { Name = "data-sys-tcindex", Value = context.Id }, null) : null); // Only render the inner blocks if the template would be rendered client-side if (!render || (actionValue == ToggleAction.Render && equals.Value) || (actionValue == ToggleAction.Dispose && !equals.Value)) { foreach (var block in Blocks) { block.Render(page, templateNames.Concat(ownTemplateNames).ToArray(), writer); } } RenderEndTag(writer); } }