1. Compiled Assembly from JSC
I've compiled what is intended to be client-side JavaScript using the JScript compiler (jsc.exe) on the server side in an attempt to make something that can be tested from a unit testing project, and maybe even something that can be debugged on the server side.
The compiled file contains only functions as follows (just for example) and it compiles fine into BitField.exe. Notice, no wrapper class or package in the source code.
------ BEGIN FILE (BitField.js) -------
function BitField(){
this.values = [];
}
// more functions ...
------- END FILE -------
jsc /fast- /out:BitField.exe Bitfield.js
Results in a BitField.exe assembly.
Success! Well, kind of ....
2. Testing Assembly / Access Point?
Secondly I've created a test project (in C#) and referenced in the BitField.exe assembly successfully. (The type of project is irrelevant but I'm providing more description to paint a full picture.)
The problem seems to be: I cannot find the namespace or a point at which I can access the BitField functions inside the BitField.exe assembly from my C# test project. The assembly doesn't seem to be a "normal".
In other words I need in C#
using ???WHAT???
Note: I don't want to use JScript "extensions", meaning keywords that won't run client-side (in a web browser), for example, class, package etc because I want the code to be clean as possible for copy & paste back into client side script environment (Regardless said "clean" code compiles fine by jsc.exe without use of those extensions). When I try to wrap the functions in package and class it starts producing compile errors so that's another reason not to use them - because they appear to make me alter my code.
Any suggestions as to how I can use the functions of the compiled JScript assembly (by having it referenced into another assembly) when there are no explicit containers in it?
Update / Proof
.NET Reflector view
After playing around with it for a while, and trying various combinations of command-line switches for jsc.exe, I'm pretty sure that what you're trying to do won't work as you'd wish it to. If you try to compile a js file that contains functions into a .Net library assembly, you get an error:
BitField.js(1,1) : error JS1234: Only type and package definitions are allowed inside a library
But, there is hope, yet! Here's what I would do...
I would keep your "clean" BitField.js file just as it is, and then create a batch file that wraps it in a JScript class and writes it out to a "dirty" js file. It's pretty clean if you think of it as part of the compilation of the code into the DLL. The code to wrap the BitField.js into BitFieldClass.js would look like this:
merge-into-class.js
var fso = new ActiveXObject("Scripting.FileSystemObject");
var ForReading = 1;
var inputFile = fso.OpenTextFile("BitField.js",ForReading, false);
var outputFile = fso.CreateTextFile("BitFieldClass.js", true);
outputFile.write("class BitFieldClass{\n");
while (!inputFile.AtEndOfStream)
{
var textLine = inputFile.ReadLine();
outputFile.write (textLine + "\n");
}
outputFile.write("}");
outputFile.close();
Then the batch file to wrap it and compile it is really simple:
compile-js.bat
cscript merge-into-class.js
jsc /t:library /out:BitFieldClass.dll bitFieldClass.js
Of course, if you wanted to do multiple files, you'd have to parameterize things a bit, but hopefully this is enough to demonstrate the idea.
Related
In ASP.NET Core, the JsonConfigurationProvider will load configuration from appsettings.json, and then will read in the environment version, appsettings.{Environment}.json, based on what IHostingEnvironment.EnvironmentName is. The environment version can override the values of the base appsettings.json.
Is there any reasonable way to preview what the resulting overridden configuration looks like?
Obviously, you could write unit tests that explicitly test that elements are overridden to your expectations, but that would be a very laborious workaround with upkeep for every time you change a setting. It's not a good solution if you just wanted to validate that you didn't misplace a bracket or misspell an element name.
Back in ASP.NET's web.config transforms, you could simply right-click on a transform in Visual Studio and choose "Preview Transform". There are also many other ways to preview an XSLT transform outside of Visual Studio. Even for web.config parameterization with Parameters.xml, you could at least execute Web Deploy and review the resulting web.config to make sure it came out right.
There does not seem to be any built-in way to preview appsettings.{Environment}.json's effects on the base file in Visual Studio. I haven't been able to find anything outside of VS to help with this either. JSON overriding doesn't appear to be all that commonplace, even though it is now an integral part of ASP.NET Core.
I've figured out you can achieve a preview with Json.NET's Merge function after loading the appsettings files into JObjects.
Here's a simple console app demonstrating this. Provide it the path to where your appsettings files are and it will emit previews of how they'll look in each environment.
static void Main(string[] args)
{
string targetPath = #"C:\path\to\my\app";
// Parse appsettings.json
var baseConfig = ParseAppSettings($#"{targetPath}\appsettings.json");
// Find all appsettings.{env}.json's
var regex = new Regex(#"appsettings\..+\.json");
var environmentConfigs = Directory.GetFiles(targetPath, "*.json")
.Where(path => regex.IsMatch(path));
foreach (var env in environmentConfigs)
{
// Parse appsettings.{env}.json
var transform = ParseAppSettings(env);
// Clone baseConfig since Merge is a void operation
var result = (JObject)baseConfig.DeepClone();
// Merge the two, making sure to overwrite arrays
result.Merge(transform, new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Replace
});
// Write the preview to file
string dest = $#"{targetPath}\preview-{Path.GetFileName(env)}";
File.WriteAllText(dest, result.ToString());
}
}
private static JObject ParseAppSettings(string path)
=> JObject.Load(new JsonTextReader(new StreamReader(path)));
While this is no guarantee there won't be some other config source won't override these once deployed, this will at least let you validate that the interactions between these two files will be handled correctly.
There's not really a way to do that, but I think a bit about how this actually works would help you understand why.
With config transforms, there was literal file modification, so it's easy enough to "preview" that, showing the resulting file. The config system in ASP.NET Core is completely different.
It's basically just a dictionary. During startup, each registered configuration provider is run in the order it was registered. The provider reads its configuration source, whether that be a JSON file, system environment variables, command line arguments, etc. and builds key-value pairs, which are then added to the main configuration "dictionary". An "override", such as appsettings.{environment}.json, is really just another JSON provider registered after the appsettings.json provider, which obviously uses a different source (JSON file). Since it's registered after, when an existing key is encountered, its value is overwritten, as is typical for anything being added to a dictionary.
In other words, the "preview" would be completed configuration object (dictionary), which is composed of a number of different sources, not just these JSON files, and things like environment variables or command line arguments will override even the environment-specific JSON (since they're registered after that), so you still wouldn't technically know the the environment-specific JSON applied or not, because the value could be coming from another source that overrode that.
You can use the GetDebugView extension method on the IConfigurationRoot with something like
app.UseEndpoints(endpoints =>
{
if(env.IsDevelopment())
{
endpoints.MapGet("/config", ctx =>
{
var config = (Configuration as IConfigurationRoot).GetDebugView();
return ctx.Response.WriteAsync(config);
});
}
});
However, doing this can impose security risks, as it'll expose all your configuration like connection strings so you should enable this only in development.
You can refer to this article by Andrew Lock to understand how it works: https://andrewlock.net/debugging-configuration-values-in-aspnetcore/
Every time I try to change a compiler constant, it seems I HAVE to:
Do a Project -> Clean.
Close Flash Builder.
Wait for it to fully close (does it's Workspace save thing...)
Re-Launch Flash Builder (and again, wait for it to finish loading...)
Re-Build All (got 3 projects dependent of eachother).
Test Run/Debug it (or Export a Release version).
This is extremely annoying and time-consuming. Is there a setting somewhere I can set so that Flash Builder ALWAYS reads the latest changes in the custom Compiler config.xml file I've made?
It basically contains something like this:
Changes to something as simple as the Version # becomes a long process.
Any workarounds?
I'm not a Flash Builder user, so take this with a pinch of salt. Some possible workarounds:
Define your constants in the project itself
Your problem seems to be that Flash Builder isn't picking up changes in an external file - from some quick searching on google, it seems to be a pretty common problem with no particular solution other than what you're doing (or going back to 4.6).
To declare your consts in the project itself, go to Project Settings > ActionScript Compiler and under Additional Compiler Arguments add your constants like so:
-define+=COMPILE::LANG_EN,true
-define+=COMPILE::LANG_FR,false
...
Each one needs to be on a separate line, and you might need to replace COMPILE with CONFIG (the default)
Build your project using ANT
It can be a bit of a pain to set up, but once it's done, you should be fine. You should be able to declare them like so:
<mxmlc ... >
<define name="CONFIG::LANG_EN" value="true"/>
<define name="CONFIG::LANG_FR" value="false"/>
</mxmlc>
Taken from http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7abd.html
Define your constants in code
It's possible to define compile constants directly in code, though it only works for the block of code it's declared in (e.g. class level). Depending on what you need it for (i.e. if you're setting up different values vs actually removing code), this could do what you need (e.g. set it up on a constants class, to set the value of different constants depending on the compile const. Then use those constants throughout your code)
package
{
config namespace COMPILE;
COMPILE const LANG_EN = true;
COMPILE const LANG_FR = !COMPILE::LANG_EN;
public class MyClass
{
public function MyClass()
{
this.sayHello();
}
COMPILE::LANG_EN
public function sayHello():void
{
trace("hello");
}
COMPILE::LANG_FR
public function sayHello():void
{
trace("bonjour");
}
public function foo():void
{
COMPILE::LANG_EN { trace( "foo" ); }
COMPILE::LANG_FR { trace( "bar" ); }
}
}
}
Change IDE
FlashDevelop can be your friend here. In the office, I work on FlashDevelop, and some of the other devs work using FlashBuilder. Each has their own strong points.
We use compiler constants defined using the first method for situations where blocks of code need to be removed (i.e. supporting mobile and web builds), and we use an embedded XML for other "constants" depending on the build; version, server ip, api keys, etc. Which XML gets embedded in the case of the latter depends on a single compiler const.
I'm trying to use Graphics32 package. Graphics32 was compiled and installed without any issue.
When I try to execute (debug) following code under C++ Builder XE3
TBitmap32* bmp = new TBitmap32();
bmp->LoadFromFile("d:\\sample.bmp");//This calls SaveToStream instead of LoadFromFile
...
it calls another member function SaveToStream which I can trace into and step while debugging until AV rises.
I have never encountered such behavior before.
Is there any compiler directive I'm missing or some workaround to make proper function call?
Update: I use the Graphics32 source from SVN. Everything works good if I use code prior to revision 2122.
So, I have an app where users should define ActionScript functions.
What do I need to get the string whritten by the user and convert it to bytecode so that I can use it with as3-commons-bytecode?
Edit
I don't think I was clear enough. I need to turn: if(!myValue) {...}
Into this:
...
findpropstrict private::myValue
getproperty private::myValue
not
iffalse L1
...
Because with this ^^^^ code, I can use as3-commons-bytecode to do what I need.
I took a look at this app's source code. It's very confusing, the project is old and the code is a mess, but it works. I need to find "where the magic happens". Can you show me the way?
You should use part of this project :
eval.hurlant.com/demo/#app=da4a&757d-selectedIndex=0
Check source , there is parser to ABC .
I'm not aware of any libraries that do this for you, but to achieve this functionality you should parse user's input into function names.
For example, you can call a function just by having it's name as a String like so:
var functionName:String = "myMethod";
function myMethod():void
{
trace("myMethod");
}
this[functionName](); //traces "myMethod"
Of course, if you wish to interpret advanced strings with getting/setting objects and their properties and any other user defined statements, that would require to write quite a sophisticated string-to-bytecode converter.
UPDATE:
There's also AS3Eval library that might do the job. Take a look at http://eval.hurlant.com/
There is a library for Haxe which makes it possible to compile Actionscript assembly language into ABC at runtime, but this is still lower-level than the Actionscript you normally write.
http://haxe.org/com/libs/format/abc
The most likely solution is a server or other process which can compile and return SWF content for you. Haxe has a very fast and straightforward compiler, but it may also be possible to use Tamarin or another solution for compiling AS3 on the server.
Actually, there is a runtime library for executing Haxe code, which again, is very similar to Actionscript. Might be worth looking into:
http://code.google.com/p/hscript/
What exactly want to do? To compile "string" the string must be something meanfull for the compiler such as package not a simply string ( like 'asdas ' ). If you don't wont to use flash/flex compiler you may compile AS to ABC with Ant or Haxe. But ther is a problem - how you will start this ABC?
Scenario: I am using Managed Extensibility Framework to load plugins (exports) at runtime based on an interface contract defined in a separate dll. In my Visual Studio solution, I have 3 different projects: The host application, a class library (defining the interface - "IPlugin") and another class library implementing the interface (the export - "MyPlugin.dll").
The host looks for exports in its own root directory, so during testing, I build the whole solution and copy Plugin.dll from the Plugin class library bin/release folder to the host's debug directory so that the host's DirectoryCatalog will find it and be able to add it to the CompositionContainer. Plugin.dll is not automatically copied after each rebuild, so I do that manually each time I've made changes to the contract/implementation.
However, a couple of times I've run the host application without having copied (an updated) Plugin.dll first, and it has thrown an exception during composition:
Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information
This is of course due to the fact that the Plugin.dll it's trying to import from implements a different version of IPlugin, where the property/method signatures don't match. Although it's easy to avoid this in a controlled and monitored environment, by simply avoiding (duh) obsolete IPlugin implementations in the plugin folder, I cannot rely on such assumptions in the production environment, where legacy plugins could be encountered.
The problem is that this exception effectively botches the whole Compose action and no exports are imported. I would have preferred that the mismatching IPlugin implementations are simply ignored, so that other exports in the catalog(s), implementing the correct version of IPlugin, are still imported.
Is there a way to accomplish this? I'm thinking either of several potential options:
There is a flag to set on the CompositionContainer ("ignore failing imports") prior to or when calling Compose
There is a similar flag to specify on the <ImportMany()> attribute
There is a way to "hook" on to the iteration process underlying Compose(), and be able to deal with each (failed) import individually
Using strong name signing to somehow only look for imports implementing the current version of IPlugin
Ideas?
I have also run into a similar problem.
If you are sure that you want to ignore such "bad" assemblies, then the solution is to call AssemblyCatalog.Parts.ToArray() right after creating each assembly catalog. This will trigger the ReflectionTypeLoadException which you mention. You then have a chance to catch the exception and ignore the bad assembly.
When you have created AssemblyCatalog objects for all the "good" assemblies, you can aggregate them in an AggregateCatalog and pass that to the CompositionContainer constructor.
This issue can be caused by several factors (any exceptions on the loaded assemblies), like the exception says, look at the ExceptionLoader to (hopefully) get some idea
Another problem/solution that I found, is when using DirectoryCatalog, if you don't specify the second parameter "searchPattern", MEF will load ALL the dlls in that folder (including third party), and start looking for export types, that can also cause this issue, a solution is to have a convention name on all the assemblies that export types, and specify that in the DirectoryCatalog constructor, I use *_Plugin.dll, that way MEF will only load assemblies that contain exported types
In my case MEF was loading a NHibernate dll and throwing some assembly version error on the LoaderException (this error can happen with any of the dlls in the directory), this approach solved the problem
Here is an example of above mentioned methods:
var di = new DirectoryInfo(Server.MapPath("../../bin/"));
if (!di.Exists) throw new Exception("Folder not exists: " + di.FullName);
var dlls = di.GetFileSystemInfos("*.dll");
AggregateCatalog agc = new AggregateCatalog();
foreach (var fi in dlls)
{
try
{
var ac = new AssemblyCatalog(Assembly.LoadFile(fi.FullName));
var parts = ac.Parts.ToArray(); // throws ReflectionTypeLoadException
agc.Catalogs.Add(ac);
}
catch (ReflectionTypeLoadException ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
}
CompositionContainer cc = new CompositionContainer(agc);
_providers = cc.GetExports<IDataExchangeProvider>();