ConflictJS is an approach that analyzes and finds conflicts between JavaScript libraries. Such conflicts may arise because libraries write to the same global memory location. If you want to include multiple libraries in a web application and are unsure whether they conflict with each other, ConflictJS can check for possible conflicts.
For details on the approach, please refer to this paper:
ConflictJS: Finding and Understanding Conflicts Between JavaScript Libraries
Jibesh Patra, Pooja N. Dixit, Michael Pradel
International Conference on Software Engineering (ICSE), 2018
The following steps are performed by ConflictJS to detect conflicts:
- Filter libraries that fail when included alone.
- Find global writes performed by each library.
- Find potentially conflicting libraries.
- Validate the potentially conflicting libraries using the following experiments:
- Check if including a pair of libraries causes an exception to occur (Inclusion test).
- If two libraries share the same global variable, check if they belong to the same type (Type test).
- If two libraries share the same global variable, and the type of variable is a non-function, check if the value of the variable is the same for both libraries (Value test).
- If two libraries share the same global variable, and the type of variable is a function, check if the behavior of variable is equivalent for both libraries (Behavior test).
We have tested ConflictJS on an Ubuntu 16.04 machine using Node.js version 7 and the Chromium browser. All dependencies must be installed before running the experiments.
We provide a script init.sh that performs all the steps mentioned below. You can either use the script or manually execute the following commands to install all dependencies.
# Install the chromium-browser
sudo apt install chromium-browser
# Install the needed node modules
npm install
# jalangi in particular needs some extra modules to be installed
cd node_modules/jalangi2
npm install
# Come back to the start directory
cd ../../
# Now, create two new directory called benchmarks and results
mkdir -p benchmarks
mkdir -p results
Let's assume that you want check whether two libraries jsurl and urljs are conflicting. All experiments should be run from the current directory
- Copy both library folders from ./benchmarks_all to ./benchmarks
cp -r benchmarks_all/jsurl/ benchmarks
cp -r benchmarks_all/urljs/ benchmarks
- Change the exports.benchmarkDir & resultDir configurations in the file src/config.js to the following
let resultDir = "results";
...
exports.benchmarkDir = "/benchmarks";
- Issue the following command
node src/runExperiments.js
This command needs to be run over and over until all experiments have finished. For this particular case, the command needs to run in total four times. The final results can be found in resultDir, as specified in the configuration file.
After running runExperiments.js often enough, several files and directories are created in the resultDir. The summary of all results is the content of validated-conflicts.json. For the particular example libraries the content of validated-conflicts.json is something like the following:
{"typeTestßjsurl,urljs°Url":"ERROR object,Function"}
The easiest way to check is to run the python3 script
python src/utilities/getValidatedConflicts.py results/validated-conflicts.json
- Each key in the JSON file represents a combination of library names and an access path. The value represents the reason for the conflict.
- The substring before the ß character denotes the experiment that found the conflict. For the example, the experiment is typeTest (Refer to Section 3.2.4 of the paper).
- Next, the names of the libraries are separated by a comma (,). For the example, the names of the libraries are jsurl and urljs.
- After the ° character comes the name of the access path over which the libraries conflict. For the example, the name of the access path is Url
- Finally, there can be some message that give details about the cause of the conflict. For the example, the type of accesspath Url differs between the two libraries. For one library, it is an object while for the other it is Function
The choice of such characters like ß and ° is driven by the fact that common characters like $ and _ are used by accesspaths or library names and we needed an easy way of separation. You can change the separation characters in the file src/config.js.
Copy any libraries for which you want to detect conflicts to the benchmarks directory and repeat the previous steps.
Let's assume we want to include a library not present in the benchmarks_all directory. Let's call this new library as test-lib.
-
Create a new folder called test-lib in the benchmarks folder.
-
Copy the library file test-lib.js to this newly created folder.
-
Create a new file called libraryInfo.json with the following content.
{ "name": "test-lib", "urls": [ "./test-lib.js" ] }
-
You may now run the experiments as mentioned in the previous steps.
-
./benchmarks_all
- Contains all libraries that has been used to test our approach.
-
./src/config.js
- Contains configurable values for the experiments.
-
./src/runExperiments.js
- The main script that starts all experiments one after the other.
-
./src/evaluation/experiments
- This folder contains the experiments that are used for the test of conflicts. runExperiments.js invokes the scripts in this directory.
-
./src/evaluation/validation-tests
- Helper scripts for the final validation experiments namely, Inclusion, Type, Value (Non functions) and Behavior (Functions)
-
./src/htmlfragments
- Fragments directory that contains HTML file templates used for running different experiments.
-
./src/utilities
- This directory contains the helper scripts for all experiments. The most important scripts in this directory are testGeneration.js used for generating tests for functions and globalWritesAnalysis.js used for finding the list of global writes of a library.
- For some libraries, the global writes analysis has bugs and might take very long time to finish.
- Generated tests do not get serialized for some libraries.
- For some access paths, the tool crashes.