I'd like to get a built in module (for example Math or path or fs), whether from the global object or require, I thought about doing something like this:
function getModuleByName(name) {
return global[name] || require(name);
}
Is there a way to check that it is indeed a module and not something else? Would this make a security problem?
Is there a way to check that it is indeed a module and not something else?
Other methods but here's an example:
function getModuleByName(name)
{
let module = null;
try {
module = require(name);
} catch (e) {
// Recommend Logging e Somewhere
}
return module;
}
This will graciously fail as null where the module does not exist, or return it.
Would this make a security problem?
Quite possibly, it depends on how it's used. I'd argue it is more of a general design issue however and would blanket say avoid doing it (without any context, you may have a very good reason).
You, like anyone, obviously have a finite amount of modules you could be loading. These modules have all been selected by yourself for your application for specific reasons, or are bundled into your node version natively and are expected parts of your environment.
What you are doing by introducing this functionality is adding the addition of unexpected elements in your environment. If you are using getModuleByName to access a third party library- you should know outright that library is available and as such there's no reason why you can't just require it directly.
--
If you do think your use case warrants this, please let me know what it is as I may never have encountered it before. I have used dynamic imports like the following:
https://javascript.info/modules-dynamic-imports
But that hasn't been for global packages/libraries, but for dynamic reference to modules built internally to the application (i.e. routing to different views, invokation of internal scripts).
These I have protected by ensuring filepaths can't be altered by whitelisting the target directories, making sure each script follows a strict interface per use case and graciously failing where a module doesn't exist (error output "this script does not exist" for the script usage and a 404 view for the routing example).
TL;DR: How can I access variables/functions/names that are defined in ES Modules from the debugger?
More context: I'm a relatively experienced JavaScript programmer, but new to Modules. I've followed the tutorial at MDN here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules. They have a good set of examples here: https://github.com/mdn/js-examples/tree/master/modules
In that collection, say in the "basic-modules" example, (live code here: https://mdn.github.io/js-examples/modules/basic-modules/) there is, for example, a function called random in the file modules/square.js. Suppose I want to execute that function in the debugger, just to try it out, or because it's my code and I want to test/debug it, or I want to demonstrate to another coder what the function does. All the stuff you expect to do in a REPL or debugger. Is there a way to do that? I've tried both the Firefox debugger and the Chrome debugger, with no luck.
Back in the pre-Modules era, that code would be put into the global namespace (making access easy) or it would be locked up in an IIFE (making access impossible) or maybe in some home-made module system (access depends). I am hoping that the new Modules system still allows the debugger access to the names inside modules.
Thanks.
It says in the docs:
Last but not least, let's make this clear — module features are imported into the scope of a single script — they aren't available in the global scope. Therefore, you will only be able to access imported features in the script they are imported into, and you won't be able to access them from the JavaScript console, for example. You'll still get syntax errors shown in the DevTools, but you'll not be able to use some of the debugging techniques you might have expected to use.
To take your example from before, you'll need to invoke that function from a scope where it is visible, i.e where it's been imported:
import { random } from 'path/to/square.js'
debugger; // you should be able to invoke random() from here
I've been working on a little project recently, and ran into this issue of actually having my project me accessible in the rest of the page.
Here's the deal:
It's a javascript router. Doing this just for the sake of interest. I've already set up my typescript compiler via grunt and my module loading and concatenation via grunt-requirejs.
Here's the grunt file: https://github.com/Forestdev/jsRoute/blob/master/gruntfile.js
The output, however, doesn't seem to generate any export to window. I have been googling as to how to export my code to window or anywhere really so that other javascript files could access it.
Could this be the problem with wrapper? Do I need to insert a custom wrapper for all of this? What's the general rule of thumb of making your typescript project global?
Edit:
Forgot to list the index file: https://github.com/Forestdev/jsRoute/blob/master/src/index.ts
Ignore the line with the new instance of an object. I want to export this object so that anyone else could create a new instance of it themselves.
Found a way to handle exposing to the global scope.
Within grunt build requirejs script I added a custom wrapper, which is:
wrap: {
start: '(function(global) {',
end: 'global.JSRoute = global.JSRoute || require("index").Router; }(window));'
}
This seems to fix the issue I had of exporting my script to a global scope. This also correctly loads the script on window load as well, so other scripts have access to it right away.
Hope this makes sense. Hopefully this is the correct way of doing it as well.
I'm having a hard time trying to pinpoint which, of the very many, methods I have in my angular app that would be causing the error:
Uncaught Error: [$injector:unpr] Unknown provider: nProvider <- n
This only happens once the javascript has been bundled & minified by ASP.Net.
I have ensured that all the controllers, and any other DI, is using the minification-safe method, I.E My controllers/service etc are using the method:
appControllers.controller('myCtrl', ['$scope', function($scope){
//......
}]);
I've gone through every JS file in our app - there are a lot... and can't find anything that violates this way of injecting dependencies - though there must be one somewhere...
Is there a better way to pinpoint which method could be causing this error?
Thanks
For anyone else struggling with this problem, I found an easier solution. If you pull open your developer console (on chrome) and add a breakpoint where angular throws the error:
Then, on the stack trace on the right, click on the first "invoke" you see. This will take you to the invoke function, where the first parameter is the function angular is trying to inject:
I then did a search through my code for a function that looked like that one (in this case grep "\.onload" -R public), and found 8 places to check.
For anybody reading this, using Angular 1.3
You can now use Angular's ng-strict-di check like this:
<div ng-app="some-angular-app" ng-strict-di>
...
</div>
This will give you an appropriate error message if you didn't load your dependencies using the array syntax.
I had the same problem and I found a solution that could be helpful for the rest. What I propose is basically what I saw in the comments and docs. If you are using Angular 1.3.0 or above, you can use this:
<html ng-app="myApp" ng-strict-di>
<body>
I can add: {{ 1 + 2 }}.
<script src="angular.js"></script>
</body>
</html>
In my case, I have everything within a file app.js so the only thing I need to do for finding my DI problems is to add this little code at the end:
angular.bootstrap(document, ['myApp'], {
strictDi: true
});
It's better documented in Angular Docs
I hope that helps. Good luck!
As mentioned in the comments, These are the steps I took to try and find my JS error.
If there is another, easier, solution, please feel free to post it and I may mark it as accepted.
Trying to debug minified code is a nightmare.
What I eventually did was copy my minified javascript, directly from the inspector in Chrome.
I then pasted the JS into http://www.jspretty.com/ - I had tried http://jsbeautifier.org/ but found their site froze with such large JS code.
Once it was 'pretty-fied' I created a test.js file in my solution and pasted the, now easier to read code, into it.
Quick step to comment out the #script tag in my _layout and add a link to the test.js file and I was ready to debug a now, far easier to read, chunk of Javascript.
It is still pretty awkward to traverse the call stack, though now you can see actual methods it makes it far less impossible.
Something that helped me solve this (finally!) was actually already in the angular docs! If you add the ng-strict-di attribute to your code wherever you define your ng-app, angular will throw a strict warning so you can more easily see what's going on in development mode. I wish that was the default!
See the argument list at the bottom of the ngApp docs.
https://docs.angularjs.org/api/ng/directive/ngApp
The way this works for me is the following:
1) have two test specification html files (unit test) minimized and plain
2) make sure the bundling of the files are in the same order as the plain spec file (JS script reference)
3) make sure to explicitly declare all dependencies (array or $inject declares see http://www.ozkary.com/2015/11/angularjs-minimized-file-unknown-provider.html)
When there is a mistake on the unit test (miminized reference) file, I can compare and make sure the reference of the files is in the correct order as the working file.
hope that help.
I had the similar issue and used lots of time to investigate and figured out it was the Chrome extension Batarang that was injecting the bad code and error in Angular looked exactly the same. It's really a pity it's so hard to find what exactly is causing the problem.
I had the similiar issue too. The solution is exacly the answer from ozkary point 3, that is to make sure to explicitly declare all dependencies including "resolve" part of your route.
Below is my code.
when('/contact/:id', {
controller: 'contactCtrl',
templateUrl: 'assets/partials/contact.html',
resolve: {
contact: ['ContactService', '$route', function(ContactService, $route) {
return ContactService.getContactDetail($route.current.params.id);
}]
}
})
For those who's bootstrapping their angularjs app.
angular.bootstrap(body, ['app'], { strictDi: true });
Don't forget to debug in non minified code and you should be able to figure out pretty quickly the malformed dependency injection.
The malformed injection is usually formatted like this :
...
.run([ function(ServiceInjected){
...
But should look more like this
...
.run(['ServiceInjected', function(ServiceInjected){
...
This is tested in angularjs 1.7.2
For testing purposes, obviously not for production. What is the best way to do this?
Googling I found this tutorial, and of course the project on github.
For starters which files do I need to run:
// removed
and is there an API reference. I see there is a large comment block in jslint.js that seems to server this purpose but was wondering if there is something easier to read.
Because the client has no file access, I was planning on ajaxing the code in to get its contents.
Please never the mind, on why I want to do this on the client.
If you include the JSLint script you will have access to a single global variable, JSLINT. You can invoke it with a string and an optional map of options:
var valid = JSLINT(code, options);
The result will be true or false, depending on whether the code passed the check based on the provided options.
After this call you can inspect the JSLINT.errors property for an array of warnings, if any.
This is precisely what I have done to build JSLint integration into the editor in the articles on http://jslinterrors.com.
Have you looked at http://jshint.com/ ? Source is available here: https://github.com/jshint/jshint/
The browser bundle is available here: http://jshint.com/get/jshint-2.1.10.js and the docs describe how to call it (http://jshint.com/docs/)