I need this because the license information, I'm looking a way to know if the app is running in debug or production mode.
If the app is running in debug mode, I need to use Windows.ApplicationModel.Store.CurrentAppSimulator otherwise I need to use Windows.ApplicationModel.Store.CurrentApp
So, I'm looking for a implementation of the function isDebug:
var currentAPP;
if (isDebug()) {
currentApp = Windows.ApplicationModel.Store.CurrentAppSimulator;
} else {
currentApp = Windows.ApplicationModel.Store.CurrentApp;
}
Any tricks?
Debug.debuggerEnabled tells you if a debugger is attached.
Note that this isn't the same as "It was compiled as debug" -- since JS isn't compiled that isn't really a meaningful indicator.
Take a look at WinJS are there #DEBUG or #RELEASE directives?
The answer there references a handy NuGet package (https://www.nuget.org/packages/WinRT-JsDebugSymbols/1.0.0) which once added and referenced in your app enables a simple check to see if it was compiled with the Debug profile:
if (Debug.isDebugBuild) {
//spot to put debug build only code
}
Given that both these methods are not entirely reliable, there is another approach through which you pick up the build target setting directly from Visual Studio, and then use that to bring in a debug or release file.
Here's how. Create two .js files in the project (debug.js and release.js in a js-buildinfo folder) and make sure to exclude them from the end package by setting their Package Action to None instead of Content (right click, select Properties, and you'll see the actions under Solution Explorer).
Here are basic file contents:
debug.js:
(function () {
"use strict";
WinJS.Namespace.define("BuildInfo", {
isDebugBuild: true,
isReleaseBuild: false,
config: "Debug",
currentApp: Windows.ApplicationModel.Store.CurrentAppSimulator
/*
* Include debug-only data, service URIs, access tokens, accounts, etc.
*/
});
})();
release.js:
(function () {
"use strict";
WinJS.Namespace.define("BuildInfo", {
isDebugBuild: false,
isReleaseBuild: true,
config: "Release",
currentApp: Windows.ApplicationModel.Store.CurrentApp
/*
* Include release-only data, service URIs, access tokens, accounts, etc.
*/
});
})();
You'd then use BuildInfo.* anywhere in your code you need to differentiate. Better still, encapsulate build-specific stuff in these files as much as you can, e.g. the CurrentApp vs. CurrentAppSimulator, calls to WinJS.Log.startLog, etc.
Then use an MSBuild task to selectively copy one or the other file to a common name in the package (e.g. buildinfo.js). To do this, it’s necessary to add a BeforeBuild action in the project file. At present, VS doesn’t allow custom build configuration for JS projects through the UI, so you have to do the following:
Right click and Unload Project in VS
Right click and Edit the project manually
Make the changes below
Right click and Reload project
Editing the .jsproj file I added the following entries under the ItemGroup with the project files:
<ItemGroup>
<BuildFlagSource Include="js-buildinfo \$(Configuration).js" />
</ItemGroup>
<ItemGroup>
<BuildFlagDestination Include="js\buildinfo.js" />
</ItemGroup>
And then farther down there’s a section that’s commented--you uncomment it and add the element shown here:
<Target Name="BeforeBuild">
<Copy SourceFiles="#(BuildFlagSource)" DestinationFiles="#(BuildFlagDestination)" OverwriteReadOnlyFiles="true" SkipUnchangedFiles="true" />
</Target>
<Target Name="AfterBuild">
</Target>
<PropertyGroup>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
Ideally you’d make buildinfo.js read-only in the project to prevent editing what will be overwritten in the build.
And the you can just have this line in whatever HTML files need it (usually before other .js files that would use the BuildInfo properties):
<script src="/js/buildinfo.js"></script>
Things I like about this solution:
It’s extensible as you can add anything you want to the debug.js and
release.js files.
The BuildInfo namespace can include methods to do build-specific work, which is sometimes necessary.
It enables isolation of all build-specific code in these files, rather than littering it throughout the rest of the app as you would with just a simple flag. I still have a flag in here as an option, but you wouldn’t have to use that at all.
It works no matter how an app is deployed.
It’s not dependent on any compiled VS extension that you’d have to produce for x86, x64, and ARM.
A few downsides:
Have to hand-edit a project and do some one-time configuration like adding a buildinfo.js and making it read-only.
You have to make sure that the debug.js and release.js files define the same stuff.
It feels a bit fragile given the manual steps.
But it does work and is the closest I've come to precompilation directive with other languages.
Related
I am working on a ScriptManager class for a project that was created many years ago. The original code read scripts from a database, and these scripts are different depending on the customer and installation (the application is a desktop app that uses Chrome Embedded Framework to display web pages). The code would read custom JavaScript code and eval() it, which of course is highly undesirable.
I am replacing this code with a ScriptManager class that can support dynamically inserted code, and the ScriptManager is capable of loading code as a module using JavaScript's dynamic import() command, or loading code as pure script by creating a script tag dynamically in the document.
My problem is that there are many different possible custom code blocks in the database, and not all are modules; some will be pure script until those can be converted to modules at a later time. My code can handle this as described above, but I need a way to detect if the script code from the database is a module, so I can either use the import() command or insert a script tag if it is not.
I am solving this temporarily by making sure any module script code has "export const isModule = true", and checking this after calling import(). This works, but any code that is pure script still results in a module variable, but with no exports in it. If possible I don't want the other developers to have to remember to add isModule = true to any modules they develop in the future.
Is there a way to check that code is a module without having to do complex analysis of the code to check if there are exports in it? Since import() still returns an object and throws no errors if there are no exports, I don't know how to detect this.
UPDATE: Here are some examples of how this is intended to work:
// Not real code, pretend that function gets the string of the script.
let code = getSomeCodeFromTheDatabase();
// Save the code for later loading.
let filename = 'some-filename.js';
saveCodeToFile(code, filename);
// Attempt to dynamically import the script as a module.
let module = await import(filename);
// If it is NOT a module, load it instead as a script tag.
// This is where I need to be able to detect if the code is
// a module or pure script.
if (!module.isModule) {
let scriptTag = document.createElement('script');
scriptTag.src = filename;
document.head.appendChild(script);
}
So if you look here How can I tell if a particular module is a CommonJS module or an ES6 module? you will see I answered a similar question.
So the thing is Sarah, modules are defined by the way that they resolve. Module-types resolving differently is what, not only makes them incompatible with one another, but it is also why we name them differently. Originally Transpillers like Babel & TypeScript were invented because of differences in ECMA-262 Specifications, and the desire to support people who didn't have the updated specifications, as well as supporting the newer features for those who did.
Today transpilers are still being used, conceptually, much the same way. They still help us maintain a single code base while supporting older specifications, and features in newer specifications, at the same time, but the also have the added benefit of being able to generate multiple different builds from a single code base. They use this to support different module types. In node.js, the primary module-type is CJS, but the future lies in ESM modules, so package maintainers have opted to dual build the projects. The use the TypeScript Compiler (aka Transpiler) to emit a CJS build, and an ESM build.
Now this is where things get complicated, because you cannot tell just by looking at a module if it CJS or ESM in this situation, **you absolutely have to inspect its code, and check if it has more than one tsconfig.json file (because it would need at-least 2 to maintain a bi-modular build (which are becoming increasingly common with the turn of each day)
My Suggestion to You:
Use well documented packages. Good packages should be documented well, and those packages should state in their README.md document, what type of package/module they are, and if the package supports more than one module type. If in doubt you can either come and ask here, or better yet, you can ask the maintainer by creating an issue, asking them to add that information to their README.md document.
You can check that there are no export after import. In chrome import() added empty default for non module.
function isNotModule(module) {
return (!Object.keys(module).length) || (!!module.default && typeof module.default === 'object' && !Object.keys(module.default).length)
}
import('./test.js')
.then((module) => {
console.log('./test.js',isNotModule(module))
})
May be it's better to check source code via regex to check if it contains export
something like this
const reg = new RegExp('([^\w]|^)export((\s+)\w|(\s*{))')
reg.test(source)
In Python there is a neat thing like this:
if __name__ == "__main__":
runTests()
So this runs runTests() only if the file was run separately and not imported. When the file will be imported it will not run the tests.
So I want to create some kind of modules for my tests in Instruments UI Automation - but I also want to test the module itself.
Is there any global variable that I can check to see if the current file is being run as a main file or as an imported one?
Good question, unfortunately the answer is no. If you are looking for something like the __name__ variable in python it does not exist. A hacky workaround that isn't really a solution to your problem (as it would require you to edit your test script before running), you could set a global variable prior to your inputs
var BEING_RUN = false;
#import "path/to/jsFile.js"
with an if statement in each file
//BEING_RUN = true;
if (BEING_RUN) {
doStuff();
}
and you could uncomment BEING_RUN = true; only on the file(s) being run. Again, this is not really a solution but it may suit your needs.
My recommendation would be to structure your test library in such a way that you don't import things from files that also contain UI tests. So you should put functions and other things that are used by your tests in files that get imported, and only have the actual simulation of user interaction in your test files. I'd also suggest checking out tuneup.js (http://www.tuneupjs.org/) it makes iOS UI Automation much more pleasant.
We have some QUnit javascript tests running in Visual Studio using the Chutzpah test adapter. Everything was working fine until we changed our api (the one being tested by the js files) recently, and added some validations over the UserAgent http header. When I tried to update the tests to change/mock the user agent I realized it was not directly possible even by overriding the default browser property.
After a few days of scavenging, I finally found what exactly is happening. Chutzpah is creating a phantomjs page object for the test files to run on. This is being done on a base javascript file (chutzpahRunner.js) located at the Chutzpah adapter installation path. These are the last lines on the file, that effectively start the tests:
...
// Allows local files to make ajax calls to remote urls
page.settings.localToRemoteUrlAccessEnabled = true; //(default false)
// Stops all security (for example you can access content in other domain IFrames)
page.settings.webSecurityEnabled = false; //(default true)
page.open(testFile, pageOpenHandler);
...
Phatomjs supports changing the user agent header by specifying it in the page settings object. If I edit this chutzpahRunner.js file in my machine, and manually set the user agent there, like this:
page.settings.userAgent = "MyCustomUserAgent";
My tests start to work again. The problem is that this is not in the project itself, and thus cannot be shared with the rest of the team.
Is it possible to change the properties of the phantomjs objects created by Chutzpah to run the tests? I'd like to either change them from inside my own tests, or from another script file I could embed on the pipeline.
Without a code change in Chutzpah it is not possible to set those properties on the PhantomJS object. Please file an issue at https://github.com/mmanela/chutzpah asking for this functionality and then fork/patch Chutzpah to add it (or wait for a developer on the project to hopefully get to this).
Update:
I pushed a fix for this issue. Once this is released you can use the following in a Chutzpah.json file:
{
"userAgent": "myUserAgent"
}
I use TypeScript to code my javascript file with Object Oriented Programing.
I want to use the node module https://npmjs.org/package/typescript-require to require my .ts files from other files.
I want to share my files in both server and client side. (Browser) And that's very important. Note that the folder /shared/ doesn't mean shared between client and server but between Game server and Web server. I use pomelo.js as framework, that's why.
For the moment I'm not using (successfully) the typescript-require library.
I do like that:
shared/lib/message.js
var Message = require('./../classes/Message');
module.exports = {
getNewInstance: function(message, data, status){
console.log(requireTs);// Global typescript-require instance
console.log(Message);
return new Message(message, data, status);
}
};
This file need the Message.js to create new instances.
shared/classes/Message.ts
class Message{
// Big stuff
}
try{
module.exports = Message;
}catch(e){}
At the end of the fil I add this try/catch to add the class to the module.exports if it exists. (It works, but it's not really a good way to do it, I would like to do better)
If I load the file from the browser, the module.export won't exists.
So, what I did above is working. Now if I try to use the typescript-require module, I'll change some things:
shared/lib/message.js
var Message = requireTs('./../classes/Message.ts');
I use requireTs instead of require, it's a global var. I precise I'm using .ts file.
shared/classes/Message.ts
export class Message{
// Big stuff
}
// remove the compatibility script at the end
Now, if I try like this and if I take a look to the console server, I get requireTs is object and Message is undefined in shared/lib/message.js.
I get the same if I don't use the export keyword in Message.ts. Even if I use my little script at the end I get always an error.
But there is more, I have another class name ValidatorMessage.ts which extends Message.ts, it's not working if I use the export keyword...
Did I did something wrong? I tried several other things but nothing is working, looks like the typescript-require is not able to require .ts files.
Thank you for your help.
Looking at the typescript-require library, I see it hasn't been updated for 9 months. As it includes the lib.d.ts typing central to TypeScript (and the node.d.ts typing), and as these have progressed greatly in the past 9 months (along with needed changes due to language updates), it's probably not compatible with the latest TypeScript releases (just my assumption, I may be wrong).
Sharing modules between Node and the browser is not easy with TypeScript, as they both use very different module systems (CommonJS in Node, and typically something like RequireJS in the browser). TypeScript emits code for one or the other, depending on the --module switch given. (Note: There is a Universal Module Definition (UMD) pattern some folks use, but TypeScript doesn't support this directly).
What goals exactly are you trying to achieve, and I may be able to offer some guidance.
I am doing the same and keep having issues whichever way I try to do things... The main problems for me are:
I write my typescript as namespaces and components, so there is no export module with multiple file compilation you have to do a hack to add some _exporter.ts at the end to add the export for your library-output.js to be importable as a module, this would require something like:
module.exports.MyRootNamespace = MyRootNamespace
If you do the above it works, however then you get the issue of when you need to reference classes from other modules (such as MyRootNamespace1.SomeClass being referenced by MyRootNamespace2.SomeOtherClass) you can reference it but then it will compile it into your library-output2.js file so you end up having duplicates of classes if you are trying to re-use typescript across multiple compiled targets (like how you would have 1 solution in VS and multiple projects which have their own dll outputs)
Assuming you are not happy with hacking the exports and/or duplicating your references then you can just import them into the global scope, which is a hack but works... however then when you decide you want to test your code (using whatever nodejs testing framework) you will need to mock out certain things, and as the dependencies for your components may not be included via a require() call (and your module may depend upon node_modules which are not really usable with global scope hacking) and this then makes it difficult to satisfy dependencies and mock certain ones, its like an all or nothing sort of approach.
Finally you can try to mitigate all these problems by using a typescript framework such as appex which allows you to run your typescript directly rather than the compile into js first, and while it seems very good up front it is VERY hard to debug compilation errors, this is currently my preferred way but I have an issue where my typescript compiles fine via tsc, but just blows up with a max stack size exception on appex, and I am at the mercy of the project maintainer to fix this (I was not able to find the underlying issue). There are also not many of these sort of projects out there however they make the issue of compiling at module level/file level etc a moot point.
Ultimately I have had nothing but problems trying to wrestle with Typescript to get it to work in a way which is maintainable and testable. I also am trying to re-use some of the typescript components on the clientside however if you go down the npm hack route to get your modules included you then have to make sure your client side uses a require compatible resource/package loader. As much as I would love to just use typescript on my client and my server projects, it just does not seem to want to work in a nice way.
Solution here:
Inheritance TypeScript with exported class and modules
Finally I don't use require-typescript but typescript.api instead, it works well. (You have to load lib.d.ts if you use it, else you'll get some errors on the console.
I don't have a solution to have the script on the browser yet. (Because of export keyword I have some errors client side) I think add a exports global var to avoid errors like this.
Thank you for your help Bill.
Is it possible to reference the javax.script.ScriptEngine library when developing an android application?
If not is there anyway possible to evaluate a javascript expression in android?
For the classes javax.script.ScriptEngine, javax.script.ScriptEngineFactory and so on, you can add the jsr223.jar to your Android project: just copy the .jar file to your libs directory, and add it from Properties->Java Build Path.
These class will allow your JSR 223-compliant engines to compile. You can then do new SomeScriptEngienFactory().getScriptEngine() to get an engine. I've managed to do this with JNLua 1.0.4 and Rhino 1.7R2.
The file jsr223.jar can be downloaded from http://www.java2s.com/Code/Jar/j/Downloadjsr223jar.htm, a direct link is http://www.java2s.com/Code/JarDownload/jsr223/jsr223.jar.zip.
javax.script.ScriptEngine is not a default part of android, but you could easily jar up any libraries you need(assuming the size is reasonable, I'm not sure) and include them in your project.
According to this post, javax.script.ScriptEngine is not available in Android SDK. You can try the steps below to include the library, but the code may not run, even though it will compile.
Using Android Development Toolkit in Windows, I performed the following steps to get javax.script library.
Right-clicked on the project, went to Properties (Project).
Under the Java Build Path, I chose Libraries tab.
Select Add Library located on the middle right of the Tab
Select JRE System Library under Add Library and click Next...
Select Workspace Default JRE (jre 7)
Click Finish.
Click Ok on the Java Build Path to exist project properties.
Javax.script was then loaded.
If you want to evaluate some code in JS in android
1) to your gradle dependencies add (rhino):
compile 'org.mozilla:rhino:1.7R4'
2) write some code like this to get the result of JS evaluation
Context rhino = Context.enter()
// turn off optimization to work with android
rhino.optimizationLevel = -1
String evaluation = "2+2"
try {
ScriptableProject scope = rhino.initStandardObjects()
String result = rhino.evaluateString(scope, evaluation, "JavaScript", 1, null).toString()
} finally {
Context.exit()
}
3) You can write more complex scripts in JS to run in the android app also (functions etc.)