Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
babel-plugin-source-wrapper
Advanced tools
Babel plugin for code instrumenting to provide meta information for objects
Babel plugin for code instrumenting by wrapping code fragments with special functions. Those functions return wrapped value (result of expression evaluating) as is, but associate (attach) meta-data to value. This data contains information about code fragment location and other details, that could be fetched by developer tools (for example component-inspector).
Babel 6
is supported. To use with Babel 5
use plugin version prior 2.0
(^1.3.3
).
Source:
var array = [1, 2, 3];
var square = function(a) {
return a * a;
};
var oddSquares = array.map(square).filter(function(n) {
return n % 2;
});
Result:
Function('...runtime...')(window,"string"==typeof DEVINFO_API_NAME?DEVINFO_API_NAME:"$devinfo");
var array = $devinfo([1, 2, 3], {
loc: "path/to/filename.js:1:13:1:22"
});
var square = $devinfo(function (a) {
return a * a;
}, {
loc: "path/to/filename.js:2:14:4:2"
});
var oddSquares = $devinfo($devinfo(array.map(square), {
loc: "path/to/filename.js:6:18:6:35"
}).filter($devinfo(function (n) {
return n % 2;
}, {
loc: "path/to/filename.js:6:43:8:2"
})), {
loc: "path/to/filename.js:6:18:8:3"
});
Now you can get a meta-data by reference:
console.log($devinfo.get(array));
// > { loc: "path/to/filename.js:1:13:1:22" }
console.log($devinfo.get(square));
// > { loc: "path/to/filename.js:2:14:4:2" }
npm install babel-plugin-source-wrapper --save-dev
babel.transform(content, {
sourceMaps: true,
plugins: [
require('babel-plugin-source-wrapper')
// or
require('babel-plugin-source-wrapper').configure({
// options
})
],
...
});
All options are optional.
String
$devinfo
Set custom name for wrap function. This function also will be host of API.
Array
or false
["/bower_compontents/**", "/node_modules/**"]
List of minimatch
masks for source filenames, which dev info should be marked as blackbox
. Info with blackbox: true
has lower priority and overrides by info without this marker.
String
or false
false
Sometimes plugin gets absolute file paths. But for some reasons relative to some location path required. In this case basePath
could be used. For example, if option is not set:
var foo = $devinfo([], {
loc: "/Users/name/git/projectpath/to/filename.js:1:11:1:13"
});
But if basePath
is set to '/Users/name/git/project'
,
var foo = $devinfo([], {
loc: "path/to/filename.js:1:11:1:13"
});
Boolean
false
If set to true
runtime API injected in every instrumented script (min version). It's add ~500 extra bytes to each script, but it's most simple way to make instrumented code works out of the box.
Example config for webpack to use plugin:
module.exports = {
// ...
devtool: 'source-map', // source maps should be used to hide wrapping code
babel: {
plugins: [
// in case you are using React, this plugin should be applied
// before babel-plugin-source-wrapper
// otherwise component names will not to be shown propertly
require('babel-plugin-react-display-name'),
require('babel-plugin-source-wrapper').configure({
// webpack sends absolute paths to plugins
// but we need paths relative to project root
basePath: process.cwd(),
// inject runtime in instrumented sources
runtime: true
})
]
}
};
If custom name for API required, config should be extended:
var webpack = require('webpack');
module.exports = {
// ...
plugins: [
new webpack.DefinePlugin({
DEVINFO_API_NAME: '"customApiName"'
})
],
babel: {
plugins: [
require('babel-plugin-source-wrapper').configure({
// ...
registratorName: 'customApiName'
})
]
}
};
Configuring babel loader for webpack.
var babelLoaderQuery = {
plugins: [
'react-display-name',
'source-wrapper'
],
extra: {
'source-wrapper': {
// webpack sends absolute paths to plugins
// but we need paths relative to project root
basePath: process.cwd(),
// inject runtime in instrumented sources
runtime: true
}
}
};
module.exports = {
// ...
loaders: [{
test: /\.jsx$/,
loader: 'babel?' + JSON.stringify(babelLoaderQuery)
}],
};
You don't need use this plugin directly with basisjs-tools
, just use basisjs-tools-instrumenter that do all necessary job for you.
Plugin package contains simple implementation of runtime API. It could be injected by plugin in every single instrumented source if runtime
option is used. Or you can inject runtime once in your html file directly:
<script src="node_modules/babel-plugin-source-wrapper/runtime.js"></script>
IMPORTANT: Script should be included before any instrumented script. Otherwise instrumented source will throw an exception about missed functions.
You could implement your own API version for instrumenting sources.
API should be presented by function, that's also host for other functions (methods). This function should return ref
value as is. Arguments:
ref
- wrapped value (result of expression)data
- meta-data, that could be attached to valueforce
- old meta-data should be overrided by new oneAdditional methods:
set(ref, data, force)
– alias for main functionget(ref)
– function to retrieve stored data for ref
wrapDecorator(decorator, wrapperData, prevValueData)
– function for wrapping ES7 decorator expressions; should return function that invokes decorator and returns it resultBoilerplate for custom implementation:
(function(){
var apiName = typeof DEVINFO_API_NAME == 'string' ? DEVINFO_API_NAME : '$devinfo';
if (window[apiName]) {
return;
}
var setter = function(ref, data, force){
// you implementation goes here
return ref;
};
var api = setter;
api.set = setter;
api.get = function(ref) {};
api.wrapDecorator = function(decorator, wrapperData, prevValueData) {
return function() {
return decorator.apply(this, arguments);
};
};
window[apiName] = api;
})();
By default API name is $devtools
. In case you need for another name there are options:
registratorName
plugin option to set name for wrapping functionDEVINFO_API_NAME
with desired name of API or replace it's occurences in source, to make known to other tools the correct name for APIMeta-data could contains those properties:
loc
(String) expression definition code fragment location, in format: filename:startLine:startColumn:endLineEnd:endColumn
blackbox
(Boolean) means that data is from blackboxed files and has low priority. Any non-blackboxed meta-data could override this data.map
(Object) if literal object is wrapped, this property contains locations for every single value.Use source maps. It can't be set up in babel
settings.
It also can be set up in your building tools setting. See webpack config for example.
Just blackbox runtime script in your browser, and you'll never see it again.
Use blackbox setting to specify library files. Info info those files has lower priority and mostly overrides by info in your sources.
React
, Backbone
and can be adopted for other frameworks. Using meta-data provided by this plugin to show details about components.Express
extension to open files from browser by GET request.MIT
FAQs
Babel plugin for code instrumenting to provide meta information for objects
We found that babel-plugin-source-wrapper demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.