dchester / jsonpath

Query and manipulate JavaScript objects with JSONPath expressions. Robust JSONPath engine for Node.js.
MIT License
1.29k stars 215 forks source link

Error when jsonpath is loaded by webpack #50

Open blobcat opened 7 years ago

blobcat commented 7 years ago

I have been trying to integrate jsonpath into my webpack project, but I'm getting blocked the following error:

Uncaught ReferenceError: Invalid left-hand side in assignment

It appears the error is coming from the following line in grammar.js when it tries to stub out require.resolve:

require.resolve = require.resolve || function() {}

The above line of code is rewritten by webpack into this, which is invalid:

!(function webpackMissingModule() { var e = new Error("Cannot find module \".\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()).resolve = !(function webpackMissingModule() { var e = new Error("Cannot find module \".\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()).resolve || function() {}

For reference, I am using webpack v2.2.0-rc.3

blobcat commented 7 years ago

I believe replacing the fs.readFileSync and require.resolve stubs by adding this code right before the export should fix the issue:

if (fs.readFileSync) {
    grammar.moduleInclude = fs.readFileSync(require.resolve("../include/module.js"));
    grammar.actionInclude = fs.readFileSync(require.resolve("../include/action.js"));
}

I cloned the repo and tested this and it works for me.

faizhasim commented 7 years ago

I am transpiling using webpack, but targeting for node (not browser). I'm getting the following error:

fs.js:954
  binding.fstat(fd, statValues);
          ^

Error: EBADF: bad file descriptor, fstat
    at Object.fs.fstatSync (fs.js:954:11)
    at tryStatSync (fs.js:456:13)
    at Object.fs.readFileSync (fs.js:493:12)
    at Object._ast.initialize._nodes (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:83075:31)
    at __webpack_require__ (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:20:30)
    at Object.<anonymous> (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:82947:16)
    at __webpack_require__ (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:20:30)
    at Object.<anonymous> (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:82676:15)
    at __webpack_require__ (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:20:30)
    at Object.<anonymous> (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:82667:19)
    at __webpack_require__ (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:20:30)
    at Object.<anonymous> (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:53419:18)
    at __webpack_require__ (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:20:30)
    at Object.defineProperty.value (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:58:32)
    at __webpack_require__ (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:20:30)
    at Object.defineProperty.value (/Users/faizhasim/dev/worth-deleting/dating-rocket/.webpack/handler.js:40:18)

I think, the check for fs.readFileSync is valid for webpack compilation targeting node. I think, we can do something like:

if (fs.readFileSync && typeof __webpack_require__ !== 'function') {
    grammar.moduleInclude = fs.readFileSync(require.resolve("../include/module.js"));
    grammar.actionInclude = fs.readFileSync(require.resolve("../include/action.js"));
}

But, I'm not sure whether it's good idea to do that. __webpack_require__ seems like an internal for webpack. Another implication is, maintenance for such edge cases. Regardless, I'm still hoping that we can find a fix.

faizhasim commented 7 years ago

My workaround for this is to treat jsonpath as an external, thus it will be loaded from node-modules, instead of bundled together by webpack. Read more at https://webpack.github.io/docs/configuration.html#externals.

My webpack config as an example for the workaround:

const path = require('path');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  entry: {
    handler: './handler.js'
  },
  output: {
    libraryTarget: 'commonjs',
    path: path.join(__dirname, '.webpack'),
    filename: '[name].js'
  },
  target: 'node',
  externals: [nodeExternals({
    whitelist: [/^(?:(?!jsonpath|aws-sdk).)*$/]
  })],
  module: {
    loaders: [{
      test: /(\.json)|(package\.json)$/,
      loader: 'json-loader'
    }, {
      test: /\.js$/,
      loader: 'babel-loader',
      exclude: /node_modules/,
      query: {
        babelrc: true
      }
    }]
  },
  resolve: {
    root: [
      path.resolve(__dirname, 'node_modules')
    ],
    extensions: ['', '.js', '.json']
  }
};
ooxi commented 6 years ago

Why is moduleInclude even needed? It contains JavaScript code as string literal and is not used inside jsonpath at all

jefftham commented 5 years ago

Is there any solution or workaround for this issue?

dingyaguang117 commented 1 year ago

any updates?

dingyaguang117 commented 1 year ago

@jefftham @faizhasim @blobcat I find another library: jsonpath-plus, which works well

brianorwhatever commented 11 months ago

The dynamic import that was merged near the beginning of this thread breaks vite/sveltekit pretty bad and I can't seem to figure out a workaround. Any ideas?

anurag-roy commented 9 months ago

@brianorwhatever I migrated to this fork: https://github.com/astronautlabs/jsonpath. Works with esm, has ts definitions, same API.