Skip to content

Commit

Permalink
Adding support for interfaces and casting in web mode, along with a test
Browse files Browse the repository at this point in the history
  • Loading branch information
Frank Laub committed Sep 19, 2009
1 parent 1057d30 commit 02dab25
Show file tree
Hide file tree
Showing 29 changed files with 367 additions and 207 deletions.
3 changes: 0 additions & 3 deletions sample/DotWeb.Sample.Script/SimpleScript.cs
Expand Up @@ -30,10 +30,7 @@ public class SimpleScript : JsScript
value = "value"
};

// var tuple = JsActivator.CreateInstance<ITuple>();

Tuple tuple = new Tuple(config);
// var foo = JsRuntime.Cast<Tuple>(tuple);
int id = tuple.id;
Console.WriteLine("id: ");
Console.WriteLine(id);
Expand Down
2 changes: 1 addition & 1 deletion src/DotWeb.Client/DotWeb.Client.csproj
Expand Up @@ -70,13 +70,13 @@
<Compile Include="Dom\Css\Style.cs" />
<Compile Include="Dom\Window.cs" />
<Compile Include="JsCodeAttribute.cs" />
<Compile Include="JsAccessible.cs" />
<Compile Include="JsException.cs" />
<Compile Include="JsHost.cs" />
<Compile Include="JsIntrinsicAttribute.cs" />
<Compile Include="JsNamespaceAttribute.cs" />
<Compile Include="JsNativeBase.cs" />
<Compile Include="JsNativeException.cs" />
<Compile Include="JsRuntime.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="JsScript.cs" />
<Compile Include="VarArgsAttribute.cs" />
Expand Down
2 changes: 1 addition & 1 deletion src/DotWeb.Client/JsAnonymousAttribute.cs
Expand Up @@ -65,7 +65,7 @@ namespace DotWeb.Client
/// </code>
/// </example>
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class JsAnonymousAttribute : Attribute
{
}
Expand Down
13 changes: 12 additions & 1 deletion src/DotWeb.Client/JsCodeAttribute.cs
Expand Up @@ -19,12 +19,23 @@

namespace DotWeb.Client
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class JsCodeAttribute : Attribute
{
public string Code { get; private set; }

public JsCodeAttribute(string code) {
this.Code = code;
}
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class JsInlineCodeAttribute : Attribute
{
public string Code { get; private set; }

public JsInlineCodeAttribute(string code) {
this.Code = code;
}
}
}
2 changes: 1 addition & 1 deletion src/DotWeb.Client/JsIntrinsicAttribute.cs
Expand Up @@ -19,7 +19,7 @@

namespace DotWeb.Client
{
[AttributeUsage(AttributeTargets.Property)]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
public class JsIntrinsicAttribute : Attribute
{
}
Expand Down
4 changes: 3 additions & 1 deletion src/DotWeb.Client/JsNamespaceAttribute.cs
Expand Up @@ -19,11 +19,13 @@

namespace DotWeb.Client
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct)]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
public class JsNamespaceAttribute : Attribute
{
public string Namespace { get; private set; }

public JsNamespaceAttribute() {
this.Namespace = string.Empty;
}

public JsNamespaceAttribute(string ns) {
Expand Down
@@ -1,30 +1,25 @@
// Copyright 2009, Frank Laub
//
// Copyright 2009, Frank Laub
//
// This file is part of DotWeb.
//
//
// DotWeb is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// DotWeb is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with DotWeb. If not, see <http://www.gnu.org/licenses/>.

//
namespace DotWeb.Client
{
/// <summary>
/// This is a marker class that tells the DotWeb system
/// that derived classes can be accessed from JavaScript.
/// A class dervied from JsAccessible will be translated into
/// JavaScript and in debug-mode, a proxy will be constructed for
/// this type.
/// </summary>
public class JsAccessible
public static class JsRuntime
{
[JsCode("return obj;")]
public static T Cast<T>(object obj) { return JsHost.Cast<T>(obj); }
}
}
}
11 changes: 0 additions & 11 deletions src/DotWeb.Client/JsScript.cs
Expand Up @@ -29,15 +29,4 @@ public class JsScript
[JsCode("console.log(obj);")]
public static void Log(object obj) { JsHost.S_(obj); }
}

public static class JsRuntime
{
public static T CreateInstance<T>() {
return default(T);
}

public static T Cast<T>(object obj) {
return JsHost.Cast<T>(obj);
}
}
}
4 changes: 2 additions & 2 deletions src/DotWeb.Decompiler/CodeModel/Member/CodeMethodMember.cs
Expand Up @@ -28,7 +28,7 @@ public class CodeMethodMember : CodeTypeMember
public CodeMethodMember() {
this.Statements = new List<CodeStatement>();
this.Parameters = new List<CodeParameterDeclarationExpression>();
this.ExternalMethods = new List<MethodBase>();
this.ExternalMethods = new HashSet<MethodBase>();
}

public CodeMethodMember(MethodBase method)
Expand All @@ -54,7 +54,7 @@ public CodeMethodMember(MethodBase method)
public string Name { get { return Info.Name; } }
public List<CodeStatement> Statements { get; set; }
public List<CodeParameterDeclarationExpression> Parameters { get; set; }
public List<MethodBase> ExternalMethods { get; set; }
public HashSet<MethodBase> ExternalMethods { get; set; }
public string NativeCode { get; set; }
}
}
6 changes: 3 additions & 3 deletions src/DotWeb.Decompiler/Core/CodeModelGenerator.cs
Expand Up @@ -327,7 +327,7 @@ class CodeModelGenerator

private void Call(ILInstruction il) {
MethodBase method = il.Operand as MethodBase;
this.vm.ExternalMethods.AddUnique(method);
this.vm.ExternalMethods.Add(method);

AssociatedProperty ap = method.GetAssociatedProperty();
if (ap != null) {
Expand Down Expand Up @@ -373,7 +373,7 @@ class CodeModelGenerator
MethodBase method = il.Operand as MethodBase;
CodeTypeReference type = new CodeTypeReference(method.DeclaringType);
CodeMethodReference expr = new CodeMethodReference(type, method);
this.vm.ExternalMethods.AddUnique(method);
this.vm.ExternalMethods.Add(method);
vm.Stack.Push(expr);
}

Expand Down Expand Up @@ -572,7 +572,7 @@ class CodeModelGenerator

private void NewObject(ILInstruction il) {
ConstructorInfo ctor = (ConstructorInfo)il.Operand;
this.vm.ExternalMethods.AddUnique(ctor);
this.vm.ExternalMethods.Add(ctor);

CodeObjectCreateExpression expr = new CodeObjectCreateExpression {
Constructor = ctor
Expand Down
4 changes: 2 additions & 2 deletions src/DotWeb.Decompiler/Core/CodeModelVirtualMachine.cs
Expand Up @@ -25,10 +25,10 @@ internal class CodeModelVirtualMachine
{
public CodeModelVirtualMachine() {
Stack = new Stack<CodeExpression>();
ExternalMethods = new List<MethodBase>();
ExternalMethods = new HashSet<MethodBase>();
}

public List<MethodBase> ExternalMethods { get; private set; }
public HashSet<MethodBase> ExternalMethods { get; private set; }
public Stack<CodeExpression> Stack { get; private set; }
}
}
2 changes: 1 addition & 1 deletion src/DotWeb.Decompiler/Core/ControlFlowGraph.cs
Expand Up @@ -36,7 +36,7 @@ class ControlFlowGraph
public List<IntervalGraph> Graphs { get; private set; }
public BasicBlock[] DfsList { get; private set; }
public bool HasCases { get; private set; }
public List<MethodBase> ExternalMethods { get; private set; }
public HashSet<MethodBase> ExternalMethods { get; private set; }

public ControlFlowGraph(MethodBase method) {
this.Method = method;
Expand Down
2 changes: 1 addition & 1 deletion src/DotWeb.Hosting.Bridge/JsBridge.cs
Expand Up @@ -245,7 +245,7 @@ public class JsBridge : IJsHost
internal object[] UnwrapParameters(JsValue[] args, DispatchType dispType, MemberInfo member) {
var fi = member as FieldInfo;
if (fi != null) {
throw new NotSupportedException("Fields are not supported JsAccessible members");
throw new NotSupportedException("Fields are not supported JsObject members");
}

MethodBase method;
Expand Down
9 changes: 8 additions & 1 deletion src/DotWeb.Translator/CodeModelExtensions.cs
Expand Up @@ -27,7 +27,6 @@ static class CodeModelExtensions
{
public static bool HasBase(this Type type) {
if (type.BaseType == typeof(object) ||
type.BaseType == typeof(JsAccessible) ||
type.BaseType == typeof(JsNativeBase)) {
return false;
}
Expand Down Expand Up @@ -80,6 +79,14 @@ static class CodeModelExtensions
return false;
}

public static bool HasJsCode(this MethodBase method) {
return method.IsDefined(typeof(JsCodeAttribute), false);
}

public static bool HasJsInlineCode(this MethodBase method) {
return method.IsDefined(typeof(JsInlineCodeAttribute), false);
}

public static bool IsAnonymous(this Type type) {
return type.IsDefined(typeof(JsAnonymousAttribute), false);
}
Expand Down
15 changes: 11 additions & 4 deletions src/DotWeb.Translator/TranslationContext.cs
Expand Up @@ -51,8 +51,7 @@ public class TranslationContext
private void GenerateMethod(MethodBase method, List<Type> typesCache, List<MethodBase> methodsCache, List<string> namespaceCache) {
var parsedMethod = Parse(method);
foreach (var external in parsedMethod.ExternalMethods) {
var externalType = external.DeclaringType;
if (IsEmittable(externalType)) {
if (IsEmittable(external)) {
if (!methodsCache.Contains(external)) {
GenerateMethod(external, typesCache, methodsCache, namespaceCache);
}
Expand Down Expand Up @@ -143,10 +142,10 @@ public class TranslationContext
if (type.Namespace != null && type.Namespace.StartsWith("System"))
return false;

if (type == typeof(object))
if (type.IsInterface)
return false;

if (type == typeof(JsAccessible))
if (type == typeof(object))
return false;

if (type.IsSubclassOf(typeof(JsNativeBase)))
Expand All @@ -165,6 +164,14 @@ public class TranslationContext
return true;
}

private bool IsEmittable(MethodBase method) {
if (method.HasJsInlineCode())
return false;

var type = method.DeclaringType;
return IsEmittable(type);
}

const BindingFlags BindingFlagsForMembers =
BindingFlags.DeclaredOnly |
BindingFlags.Public |
Expand Down
9 changes: 9 additions & 0 deletions src/DotWeb.Utility/ListExtensions.cs
Expand Up @@ -22,6 +22,15 @@

namespace DotWeb.Utility
{
//public static class HashSetExtensions
//{
// public static void AddRange<T>(this HashSet<T> set, IEnumerable<T> items) {
// foreach (var item in items) {
// set.Add(item);
// }
// }
//}

public static class ListExtensions
{
public static bool AddUnique<T>(this List<T> list, T item) {
Expand Down
5 changes: 1 addition & 4 deletions test/DotWeb.Hosting.Test/DotWeb.Hosting.Test.csproj
Expand Up @@ -54,14 +54,11 @@
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CachingObjectFactory.cs" />
<Compile Include="JsBridgeTest_Source.cs" />
<Compile Include="JsBridgeTest.cs" />
<Compile Include="JsFunctionTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down

0 comments on commit 02dab25

Please sign in to comment.