requireJS, origin of the define statement - javascript

I'm working on a large project that uses Requirejs for dependency management, specifically the convention is for every file to have this pattern:
define(['dependency1', 'dependency2'], function (dependency1, dependency2) {
... some code ...
});
now I'm investigating a failure where some file is trying to require a dependency that no longer exists.
I'm getting this error from RequireJS:
GET https://some-location/some-file.js net::ERR_ABORTED
Uncaught Error: Script error for: some-file
http://requirejs.org/docs/errors.html#scripterror
at C (require.min.js:8)
at HTMLScriptElement.onScriptError (require.min.js:29)
at HTMLScriptElement.nrWrapper (...)
How can I know which file contains the faulty dependency?
Simply searching the project files is not good enough since it is a large project that spans across multiple code bases.
Is there a way to make RequireJS tell me who asked for it?

What version of requirejs are you using? I'm using 2.3.2 and the error output provide more info, take a look:
GET http://localhost:9090/requirejs/js/dependency1.js net::ERR_ABORTED
require.js:168 Uncaught Error: Script error for "home/dependency1",needed by: home/somefile
http://requirejs.org/docs/errors.html#scripterror
at makeError (require.js:168)
at HTMLScriptElement.onScriptError (require.js:1735)
Please, note that the part that says needed by: home/somefile is telling us the file that is requiring the failed dependency. This is the small local test I did.
requirejs config
require.config(
{
paths: {
'home': './js'
},
callback: function() {
require(['home/somefile'], function(a) {
console.log(a);
});
}
}
);
./js/somefile.js
define(['home/dependency1'], function (dependency1) {
console.log(dependency1);
});
So, after getting the error Uncaught Error: Script error for "home/dependency1",needed by: home/somefile, we can say that the file requiring the failed dependency is PATH_TO_OUR_PROJECT/js/somefile.js. Remember that we need to pay attention to our paths in the require config.
You can play and test the Global requirejs.onError function but it won't give you more info than the regular requirejs output.
More info in Handling Errors from docs.
Hope it helps.

Following Castro Roy's answer i made a test to verify this is indeed issue of requireJS version.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Require Test</title>
<script data-main="main" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.2/require.min.js"></script>
</head>
<body></body>
</html>
main.js
requirejs(['someFile'], function(someFile) {
console.log('main executing')
});
someFile.js
define(['someDependency'], function (someDependency) {
console.log('someFile executing')
});
and someDependency.js obviously missing.
Results:
using requireJs 2.1.20 (used in my project)
GET http://localhost:63342/playground-simple/someDependency.js net::ERR_ABORTED
Uncaught Error: Script error for: someDependency
http://requirejs.org/docs/errors.html#scripterror
at makeError (require.min.js:1)
at HTMLScriptElement.onScriptError (require.min.js:1)
Then again using requireJs 2.3.2
GET http://localhost:63342/playground-simple/someDependency.js net::ERR_ABORTED
Uncaught Error: Script error for "someDependency", needed by: someFile
http://requirejs.org/docs/errors.html#scripterror
at makeError (require.js:168)
at HTMLScriptElement.onScriptError (require.js:1735)
So clearly Yes.
This is an issue of version and not some unique behavior of my project and this information is given in the error message for later versions of require.
sadly i was not able to find any documentation for this change

Related

JS module throwing error upon declaration

I have a webpage (.ejs) that calls a separate file to contain the necessary JS, as here:
<html lang="en">
<head>
//stuff
</head>
<body>
//stuff
<script type="module" src="/public/js/p2p_logic.js"></script>
</body>
</html>
With the corresponding JS as here:
//p2p_logic.js
addEventListener("load", connect);
addEventListener("load", initialize);
//stuff
function connect() {
console.log("FIRED CONNECT");
} //connect()
function initialize() {
console.log("FIRED INITIALIZE");
import WebRTCAdaptor from "./public/js/webrtc_adaptor.js"
} //initialize()
As can be seen, the JS file calls an 'import'. I am having great difficulty getting this to be operative. I have never used an 'import' within a JS script file (attached to an HTML/EJS page) before. As written above, I am receiving this error:
Uncaught SyntaxError: Unexpected identifier p2p_logic.js:27
I have also attempted to use 'curly' brackets, as here:
import {WebRTCAdaptor} from "./public/js/webrtc_adaptor.js"
However this seems to have no effect. If I modify the JS file to 'import' on the initial line, as here:
//p2p_logic.js
import WebRTCAdaptor from "./public/js/webrtc_adaptor.js"
addEventListener("load", connect);
addEventListener("load", initialize);
//stuff
function connect() {
console.log("FIRED CONNECT");
} //connect()
function initialize() {
console.log("FIRED INITIALIZE");
} //initialize()
This throws a 404 error...which indicates a 'file not found'. Specifically:
Failed to load resource: the server responded with a status of 404 () webrtc_adaptor.js:1
That however is BS since the file is definitely in the './public/js' directory...the 'webrtc_adapter.js' file is in the same directory as the 'p2p_logic.js' file...but I am using an absolute path structure so I don't see how that would matter...?
I am beginning to think it is not possible to perform an 'import' of a file in this manner...I have never had an issue using an external JS file in conjunction with a HTML/EJS page before...however in those cases I never made usage of an 'import' statement.
Does anybody know if it is even possible to 'import' using an external JS file attached to a HTML/EJS page?
You have script tags inside your .js file which is throwing an error because those are html and you can't have that in a JavaScript file. Remove those and you should be good
I have the 'import' problem now resolved...I had included a period (".") within the path that should not have been there...which is why I was seeing a 404 error being thrown. The correct 'import' path should have been '/public/js/...' instead of './public/js/...' Thanks again to those that responded.

How to import another JS file in a Web Worker?

I've got a WebWorker in which I want to use functions from another existing JavaScript file. I've tried different methods to import the JS file but so far none have worked. The file in question is in another directory, with relate path '../pkg/benchmark.js'.
Is there anyone who knows how to do this?
I've tried the following methods:
Method 1:
import * as myFile from '../pkg/benchmark.js';
which gives the errors:
Uncaught SyntaxError: Unexpected token *
Method 2:
import { myFunc1, myFunc2 } from '../pkg/benchmark.js';
gives the error:
Uncaught SyntaxError: Unexpected token {
Method 3:
Using importScripts()
importScripts('../pkg/benchmark.js');
gives the error:
worker_wasm.js:6 Uncaught DOMException: Failed to execute importScripts' on 'WorkerGlobalScope': The script at http://localhost:8080/pkg/benchmark.js' failed to load.
Method 4:
Using dynamic imports:
import('../pkg/benchmark.js')
.catch(e => console.error(e));
gives the error:
TypeError: Failed to fetch dynamically imported module: http://localhost:8080/pkg/benchmark.js
Since I'm using npm, it should be mentioned that in package.json I've defined the dependency
"dependencies": {
"benchmark": "file:../pkg"
}
so I normally don't have to specify the relative path, and instead just import 'benchmark' directly. This doesn't work either.
Method 5:
Finally, I've tried enabling the chrome flag
--enable-experimental-web-platform-features
and declare my worker as
new Worker("worker.js", { type: "module" });
which doesn't give any errors in the developer console but also doesn't run the imported functions.

Typescript include modules in browser?

I am just getting started with TypeScript (and front end development in general) coming from a c# background so sorry if this is a really basic question, but I can't figure out where I'm going wrong...
What I'm trying to do for now is create a really basic program to retrieve some sample data from a url in JSON format, parse to TS classes, and display it on the page.
In order to get the json response I found this answer that recommends using a node package. I got it installed and it seems to be ok (at least TS doesn't give me any errors).
I also figured out that I need to compile (not sure if that's the right term?) with Browserify to make it browser compatible since it's using a node module. I did that but now when I try to run in a browser it's telling me my method is not defined.
export class Keynote {
KeyValue: string;
Description: string;
Parent: string;
}
Retrieval class is:
import {Keynote} from "./Keynote";
import * as request from "request-promise-native";
function GetKeynotes(): Array<Keynote> {
const baseUrl = 'https://revolutiondesign.biz/Sandbox/TypeScript/KeynoteProvider.php';
var options = {uri: baseUrl};
const result = JSON.parse(request.get(options));
return result;
}
and html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Keynotes Testing</title>
<script src="bundle.js"></script>
<script>
function Retrieve() {
var notes = GetKeynotes();
document.getElementById('container').innerText = JSON.stringify(notes);
}
</script>
</head>
<body>
<div>
<button content="Get some notes" onclick="Retrieve()">Get some notes</button>
</div>
<div id="container">
</div>
</body>
</html>
Browserify is really long so I didn't want to copy here but you can see it at https://revolutiondesign.biz/Sandbox/TypeScript/KeynoteDisplay.html in the source if you want.
When I click the button I get this error in the browser:
KeynoteDisplay.html:9 Uncaught ReferenceError: GetKeynotes is not defined
at Retrieve (KeynoteDisplay.html:9)
at HTMLButtonElement.onclick (KeynoteDisplay.html:16)
Retrieve # KeynoteDisplay.html:9
onclick # KeynoteDisplay.html:16
GetKeynotes is defined in my typescript, and on the 5th line of bundle.js I see a function with that name... Why is it undefined?
UPDATE
Ok I have played with jspm and SystemJs but I still don't have something right. I referenced the module with jspm and did a bundle to build.js and uploaded the whole thing just to make sure everything is there. Here are the tags in my html for scripts:
<script src="../../jspm_packages/system.js"></script>
<script src="../../config.js"></script>
<script src="build.js"></script>
<script>
System.import("Sandbox/TypeScript/build.js")
function Retrieve() {
System.import("Sandbox/TypeScript/build.js")
var notes = GetKeynotes();
document.getElementById('container').innerText = JSON.stringify(notes);
}
</script>
When I press the button I can debug in my function, but it still gives the error, 'GetKeynotes is not defined' just like before... Again I can see a function with that name in the build.js file so I don't understand why it's not finding it.
I also tried System.import("Sandbox/TypeScript/KeynoteRetrieval.js") but it gives the error:
Uncaught (in promise) Error: (SystemJS) Node tls module not supported in browsers.
Error loading https://revolutiondesign.biz/Sandbox/TypeScript/KeynoteRetrieval.js

Issues Integrating ACE Editor with Keystonejs App

It says here(http://ace.c9.io/#nav=embedding) just copy one of src* subdirectories somewhere into your project
I have put it in mykeystoneapp/public/js(my default home is mykeystoneapp/public)
Here are the errors I get:
1.Uncaught TypeError: $.cookie is not a function(ui.js:8)
2.Uncaught Error: Missed anonymous define() module: function …(require.js:141)
http://requirejs.org/docs/errors.html#mismatch
Here is my Jade code:
script(src='/js/ace/demo/kitchen-sink/require.js')
script.
require.config({paths: {ace: "/js/ace/build/src"}});
define('testace', ['ace/ace'],
function(ace, langtools) {
console.log("This is the testace module");
var editor = ace.edit("editor_container");
editor.setTheme('eclipse');
editor.session.setMode('javascript');
require(["/js/ace/lib/ace/requirejs/text!src/ace"], function(e){
editor.setValue(e);
})
});
require(['testace']);
Secondly if I put debugger in EventEmitter(https://github.com/ajaxorg/ace-builds/blob/master/src/ace.js#L3300)
I can see it’s properly reaching EventEmitter._dispatchEvent with
eventName=‘changeMode’ but it returns without any operation as there are no !listeners or defaultHandler
editor.session.setMode('javascript'); is wrong, it should be editor.session.setMode('ace/mode/javascript'); instead. Same for theme which is supposed to be ace/theme/eclipse.
error in ui.js is not related to ace, since ace doesn't have a file named ui.

Logging with grunt and qunit

I am running javascript unittests with grunt/qunit. Sometimes the tests fails because of e.g syntax errors in the source files (works fine with file info if syntax errors are introduced in the test files). When that happens grunt simply prints the line number and not the file where the problem is.
Running "qunit:all" (qunit) task
Warning: Line 99: Unexpected identifier Use --force to continue.
Aborted due to warnings.
This does not help much since I have 100 of js files. I have looked into:
https://github.com/gruntjs/grunt-contrib-qunit
and tried to add the following to my Gruntfile.js (grunt.event.on):
module.exports = function(grunt) {
"use:strict";
var reportDir = "output/reports/"+(new Date()).getTime().toString();
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
qunit: {
options: {
'--web-security': 'no',
coverage: {
src: ['../src/**/*.js'],
instrumentedFiles: 'output/instrument/',
htmlReport: 'output/coverage',
coberturaReport: 'output/',
linesTresholdPct: 85
}
},
all: ["testsSuites.html"]
}
});
// Has no effect
grunt.event.on('qunit.error.onError', function (msg, stack) {
grunt.util._.each(stack, function (entry) {
grunt.log.writeln(entry.file + ':' + entry.line);
});
grunt.warn(msg);
});
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-qunit-istanbul');
grunt.registerTask('test', ['qunit']);
Where testsSuites.html contains:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="qunit/qunit.css">
<script src="qunit/qunit.js"></script>
<script src="sinonjs/sinon-1.7.3.js"></script>
<script src="sinonjs/sinon-qunit-1.0.0.js"></script>
<!-- Sources -->
<script src="../src/sample.js"></script>
<!-- Test-->
<script src="test/sample-test.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script>
</script>
</body>
</html>
But the source file where the problem is located is still not printed. Is is out of Grunts hands to verify source code/show line number/file where e.g a syntax error is located?
I have also tried running:
grunt test --debug 9
It prints some debug info but not any information regarding syntax errors in the javascript sources.
I have tried to install JSHint and call it on all my javascript source files:
for i in $(find ../src -iname "*.js"); do jshint $i; done
Now I get tons of errors but Grunt is still happy. If I introduce a simple syntax error e.g:
(function(){
var sampleVar 32;
}
to provoke an error in Grunt:
Running "qunit:all" (qunit) task
Warning: Line 2: Unexpected number Use --force to continue.
Aborted due to warnings.
it simply disappears in the stream of errors generated by JSHint. How do I filter JSHint "warnings" from critical errors that will actually make Grunt fail?
Or is it qunit that should be configured for more verbose output?
grunt-contrib-qunit will display filenames when encountering a syntax error. Take this simplified version of your Gruntfile.js:
module.exports = function(grunt) {
"use:strict";
grunt.initConfig({
qunit: {
options: { '--web-security': 'no' },
all: ["testsSuites.html"]
}
});
grunt.loadNpmTasks('grunt-contrib-qunit');
};
Running it gives the error you're looking for:
$ grunt qunit
Running "qunit:all" (qunit) task
Testing testsSuites.html F.
>> global failure
>> Message: SyntaxError: Parse error
>> file:///tmp/src/sample.js:2
Warning: 1/2 assertions failed (17ms) Use --force to continue.
Aborted due to warnings.
The issue you're having looks to be a bug(?) in grunt-qunit-istanbul. The warning you're getting:
Warning: Line 99: Unexpected identifier Use --force to continue.
is Grunt handling an uncaught exception. The exception is being raised by the grunt-qunit-istanbul task. You can prove it by modifying this line in your original Gruntfile.js from:
src: ['../src/**/*.js'],
to:
src: ['../src/**/*.js.nomatch'],
This will prevent grunt-qunit-istanbul from finding and parsing any Javascript files before Qunit is run. If you let Qunit run, its error handler prints out the filenames with syntax errors like you want.
The only fix is the workaround I've described, or to patch grunt-qunit-istanbul to add an error handler for parse errors like Qunit does.
Patching grunt-qunit-istanbul
The function that is throwing the exception is Instrumenter.instrumentSync, which it is supposed to do:
instrumentSync ( code, filename )
Defined in lib/instrumenter.js:380
synchronous instrumentation method. Throws when illegal code is passed to it
You can fix it by wrapping the function call:
diff -r 14008db115ff node_modules/grunt-qunit-istanbul/tasks/qunit.js
--- a/node_modules/grunt-qunit-istanbul/tasks/qunit.js Tue Feb 25 12:14:48 2014 -0500
+++ b/node_modules/grunt-qunit-istanbul/tasks/qunit.js Tue Feb 25 12:19:58 2014 -0500
## -209,7 +209,11 ##
// instrument the files that should be processed by istanbul
if (options.coverage && options.coverage.instrumentedFiles) {
- instrumentedFiles[fileStorage] = instrumenter.instrumentSync(String(fs.readFileSync(filepath)), filepath);
+ try {
+ instrumentedFiles[fileStorage] = instrumenter.instrumentSync(String(fs.readFileSync(filepath)), filepath);
+ } catch (e) {
+ grunt.log.error(filepath + ': ' + e);
+ }
}
cb();
Then the test will keep running (and inform you of the syntax error):
$ grunt qunit
Running "qunit:all" (qunit) task
>> /tmp/src/sample.js: Error: Line 2: Unexpected number
Testing testsSuites.html F.
>> global failure
>> Message: SyntaxError: Parse error
>> file:///tmp/src/sample.js:2
Warning: 1/2 assertions failed (19ms) Use --force to continue.
Aborted due to warnings.
I have used grunt-contrib-qunit in the past but I have never attempted something like this. The problem you are facing is fairly interesting because the docs mention that the event qunit.error.onError should be emitted by grunt but it is not happening for you.
I created a new project using a jquery template and changed the code so that my test would fail. After that I wrote the following code:
grunt.event.on('qunit.error.onError', function(message, stackTrace) {
grunt.file.write('log/qunit-error.log', message);
});
When I ran the command grunt, I received no output in the file. To check this, I made a change to the event:
grunt.event.on('qunit.log', function(result, actual, expected, message, source) {
grunt.file.write('log/qunit-error.log', message);
});
Now, this piece of code did give me the error message in my file but it was useless because I could not get the stacktrace or the exact error message.
After this, I though of reading up the source and this is what I found:
phantomjs.on('error.onError', function (msg, stackTrace) {
grunt.event.emit('qunit.error.onError', msg, stackTrace);
});
The grunt event is only emitted when phantomjs throws an error.
At the moment I am not sure how I can get a phantomjs error while testing a simple JavaScript file without any browser related testing. This is my analysis so far and I hope this helps you in someway.

Categories

Resources