Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

Error using array of importers #1168

Closed
SpenceDiNicolantonio opened this issue Sep 22, 2015 · 22 comments
Closed

Error using array of importers #1168

SpenceDiNicolantonio opened this issue Sep 22, 2015 · 22 comments

Comments

@SpenceDiNicolantonio
Copy link

I get the following error when providing an array of importers (including when the array contains a single importer):

TypeError: bridge.success is not a function
    at done (<app path>/node_modules/node-sass/lib/index.js:306:20)
    at Object.options.importer.(anonymous function) (<app path>/node-sass/lib/index.js:312:13)
    at Object.options.importer.(anonymous function) (<app path>/node_modules/node-sass/lib/index.js:309:32)
    at options.importer.(anonymous function) (<app path>/node_modules/node-sass/lib/index.js:309:32)
@xzyfer
Copy link
Contributor

xzyfer commented Sep 22, 2015

Please either provide a fully functional example of this error or provide a
gist of your node sass config and the importers your using.

Also at the very minimum provide us with the version of node sass you're
using.
On 22 Sep 2015 14:13, "Spence DiNicolantonio" notifications@github.com
wrote:

I get the following error when providing an array of importers (including
the array contains a single importer):

TypeError: bridge.success is not a function
at done (/node_modules/node-sass/lib/index.js:306:20)
at Object.options.importer.(anonymous function) (/node-sass/lib/index.js:312:13)
at Object.options.importer.(anonymous function) (/node_modules/node-sass/lib/index.js:309:32)
at options.importer.(anonymous function) (/node_modules/node-sass/lib/index.js:309:32)


Reply to this email directly or view it on GitHub
#1168.

@SpenceDiNicolantonio
Copy link
Author

I'm attempting to use node-sass-json-importer, and node-sass-import-once.

This error occurs in any case in which the importer(s) are specified within an array, regardless of which importer(s) are declared.

I am using gulp-sass 2.0.4 with node-sass 3.3.3. It is my understanding that the importer option is unaffected by gulp-sass and passed directly, as is, to node-sass

Here is my target use case:

        return gulp.src(config.styles.src)
            .pipe(sass({
                importer: [importOnce, jsonImporter],
                includePaths: [config.appRoot],
                sourceComments: 'map',
                outputStyle: 'nested'
            }))

The error also occurs in these use cases:

        return gulp.src(config.styles.src)
            .pipe(sass({
                importer: [jsonImporter],
                ...
            }))
        return gulp.src(config.styles.src)
            .pipe(sass({
                importer: [importOnce],
                ...
            }))

However, these use cases work just fine:

        return gulp.src(config.styles.src)
            .pipe(sass({
                importer: jsonImporter,
                ...
            }))
        return gulp.src(config.styles.src)
            .pipe(sass({
                importer: importOnce,
                ...
            }))

@saper
Copy link
Member

saper commented Sep 23, 2015

Assuming you have meant

var gulp = require('gulp-sass')

your examples result in

return gulp.src(config.styles.src)
                ^

ReferenceError: config is not defined
    at Object.<anonymous> (/home/saper/sw/nodes-sass-problems/1168/test:2:17)

Please provide a self-contained, working script - preferably without gulp-sass, if that's possible.

@ruslansavenok
Copy link

Have same bug using gulp-sass

importer: [function(url) {
    var regexp = new RegExp('^(' + paths.shortcutCommonScss + ')');

    if(regexp.test(url)) {
      return {
        file: paths.commonScss + url.split(paths.shortcutCommonScss)[1]
      }
    }

    return {
      file: url
    }
}]

returns error:

...../node_modules/gulp-sass/node_modules/node-sass/lib/index.js:305
            bridge.success(data);
                   ^
TypeError: undefined is not a function
    at done (..../node_modules/gulp-sass/node_modules/node-sass/lib/index.js:305:20)
    at Object.options.importer.(anonymous function) (..../node_modules/gulp-sass/node_modules/node-sass/lib/index.js:311:13)
    at options.importer.(anonymous function) (..../node_modules/gulp-sass/node_modules/node-sass/lib/index.js:308:32)

with adding some console.log-s in node-sass/lib/index.js i found out that it runs done() on importer twice, where in one bridge = {success:....} and in other bridge = function done(data) {...}

@safareli
Copy link

safareli commented Nov 2, 2015

I'm also having this issue too

@saper
Copy link
Member

saper commented Nov 7, 2015

I need a way to reproduce this without gulp-sass. Please post a self-contained, complete example of how to reproduce this bug.

@safareli
Copy link

safareli commented Nov 7, 2015

tried this but it works ok

var sass =  require('node-sass');
var importer =  function (url, file, done) {
  return done({file: url});
};

console.log(sass.renderSync({
  data: "body{ color:red; }",
  importer: [importer,importer]
}))

@saper
Copy link
Member

saper commented Nov 7, 2015

That's why I think gulp-sass is interfering...

@xzyfer
Copy link
Contributor

xzyfer commented Nov 28, 2015

@safareli I am unable to produce your error with gulp-sass.

$ npm ls --depth=1 | grep sass
/Users/michael/tmp/gulp-sass-bug
└─┬ gulp-sass@2.1.0
  ├── node-sass@3.4.2
var gulp = require("gulp");
var sass = require("gulp-sass");

var importer = function (url, file, done) {
  return done({file: url});
};

gulp.task("sass", function() {
  return gulp.src("foo.scss")
    .pipe(sass({
      importer: [importer, importer] 
    }))
    .pipe(gulp.dest("."));
})
foo { bar: baz }

@xzyfer
Copy link
Contributor

xzyfer commented Nov 28, 2015

@ruslansavenok I am unable to reproduce your error.

$ npm ls --depth=1 | grep sass
/Users/michael/tmp/gulp-sass-bug
└─┬ gulp-sass@2.1.0
  ├── node-sass@3.4.2
var gulp = require("gulp");
var sass = require("gulp-sass");

var importer = function (url, file, done) {
  if (true) {
    return {file: url};
  }
  return {file: url};
};

gulp.task("sass", function() {
  return gulp.src("foo.scss")
    .pipe(sass({
      importer: [importer, importer] 
    }))
    .pipe(gulp.dest("."));
})
// foo.scss
@import "bar";

foo { bar: baz }
// bar.scss
foo { bar: baz }

@xzyfer
Copy link
Contributor

xzyfer commented Nov 28, 2015

@SpenceDiNicolantonio I am unable to reproduce your error.

$ npm ls --depth=1 | grep sass
/Users/michael/tmp/gulp-sass-bug
├─┬ gulp-sass@2.1.0
│ ├── node-sass@3.4.2
├─┬ node-sass-import-once@1.2.0
└─┬ node-sass-json-importer@1.0.4
var gulp = require("gulp");
var sass = require("gulp-sass");
var importOnce = require("node-sass-import-once");
var jsonImporter = require("node-sass-json-importer");


gulp.task("sass", function() {
  return gulp.src("foo.scss")
    .pipe(sass({
      importer: [importOnce, jsonImporter] 
    }))
    .pipe(gulp.dest("."));
})
// foo.scss
@import "bar";

foo { bar: baz }
// bar.scss
foo { bar: baz }

@xzyfer
Copy link
Contributor

xzyfer commented Nov 28, 2015

Closing until there is more information.

@xzyfer xzyfer closed this as completed Nov 28, 2015
@safareli
Copy link

issue was with node-sass 2.0.4 you are using newer version of it. so it looks like it that hase been fixed

@antixrist
Copy link

I have the same bug.

This code works fine:

var nodeSass          = require('node-sass'),
    sassCssImporter   = require('node-sass-css-importer');

var scssFilename = 'app/styles.css.scss';
var importPaths = [
    'bower_components/magnific-popup/dist'
];

var result = nodeSass.renderSync({
      file: scssFilename,
      // not array:
      importer: sassCssImporter({
        import_paths: importPathes
      })
});

However, when I pass an array then i get an error:
TypeError: bridge.success is not a function

var nodeSass          = require('node-sass'),
    sassCssImporter   = require('node-sass-css-importer');

var scssFilename = 'app/styles.css.scss';
var importPaths = [
    'bower_components/magnific-popup/dist'
];

var result = nodeSass.renderSync({
      file: scssFilename,
      // array:
      importer: [sassCssImporter({
        import_paths: importPathes
      })]
});

Versions from node-sass's package.json:

"version": "3.4.2",
"libsass": "3.3.2",

@xzyfer
Copy link
Contributor

xzyfer commented Dec 27, 2015

@antixrist I think this is likely a bug in node-sass-css-importer. They're returning done() which would be running into #1296.

@HairyRabbit
Copy link

HairyRabbit commented Jun 15, 2016

Hi. I got a same issue with gulp-sass.

One file is work fine, but more than one file will throw this error.

|- src/
     |- index.scss
     |- index2.scss
     |- lib\
         |- _test.scss

index.scss and index2.scss has same contents:

// index.scss & index2.scss
@import 'lib/test'

// lib/_test.scss
.test { color: pink; }
const gulp = require('gulp')
const sass = require('gulp-sass')

gulp.task('default', () => {
    return gulp.src('src/*.scss')
    .pipe(sass({
        importer: [url => ({ file: url })]
    }))
    .pipe(gulp.dest('tmp'))
})

Got this output:

F:\node_modules\node-sass\lib\index.js:299
            bridge.success(result === module.exports.NULL ? null : result);
                   ^
TypeError: bridge.success is not a function
    at done (F:\gulp-sass-test\node_modules\node-sass\lib\index.js:299:20)
    at Object.options.importer.(anonymous function) (F:\gulp-sass-test\node_modules\node-sass\lib\index.js:305:13)
    at options.importer.(anonymous function) (F:\gulp-sass-test\node_modules\node-sass\lib\index.js:302:32)

Versions:

node-sass       3.7.0   (Wrapper)       [JavaScript]
libsass         3.3.6   (Sass Compiler) [C/C++]
-----
gulp:
CLI version 1.2.1
Local version 3.9.1

Any help

Thanks :)

@xzyfer
Copy link
Contributor

xzyfer commented Jun 15, 2016

@yuffiy thank you for your thorough update. I have long suspected there was an issue here but was unable to track it down until now.

@xzyfer xzyfer reopened this Jun 15, 2016
xzyfer added a commit to xzyfer/gulp-sass that referenced this issue Jun 15, 2016
Currently options are leaking between compilation runs. This is most
evident when using an array of importers. The array is shallow copied
internally, and the children of that array are wrapped by Node Sass.

When the next file is compiled the options are shallow copied once
again however this time the importer array contains the wrapped
importers not the original ones.

Instead of shallow copying with `Object.assign` this patch does a
full deep clone. Node Sass should also do this to prevent mutating
the options being passed in.

Related sass/node-sass#1168
Fixes dlmanning#467 (probably)
@xzyfer
Copy link
Contributor

xzyfer commented Jun 15, 2016

There is a bug with both gulp-sass and node-sass when using an array of importers. The importers array is mutated each time render is called which eventually causes an error to occur. The options passed into render and renderSync should be cloned but currently they're just shallow copied.

The problem is exaggerated when gulp-sass is used. See dlmanning/gulp-sass#509

@xzyfer xzyfer added this to the next.patch milestone Jun 15, 2016
@xzyfer xzyfer self-assigned this Jun 15, 2016
xzyfer added a commit to xzyfer/gulp-sass that referenced this issue Jun 15, 2016
Currently options are leaking between compilation runs. This is most
evident when using an array of importers. The array is shallow copied
internally, and the children of that array are wrapped by Node Sass.

When the next file is compiled the options are shallow copied once
again however this time the importer array contains the wrapped
importers not the original ones.

Instead of shallow copying with `Object.assign` this patch does a
full deep clone. Node Sass should also do this to prevent mutating
the options being passed in.

Related sass/node-sass#1168
Fixes dlmanning#467 (probably)
@xzyfer
Copy link
Contributor

xzyfer commented Jun 15, 2016

gulp-sass@v2.3.2 has been release which should address this issue for gulp-sass users.

@HairyRabbit
Copy link

@xzyfer ❤️

xzyfer added a commit to xzyfer/node-sass that referenced this issue Jun 15, 2016
The options object passed into `render` and `renderSync` is only
shallow copied. This is an issue when nested objects and arrays like
custom importer and functions. In the case of custom function we
wrap the provided function. This wrapped version replaces the provided
one which can then leak back into the calling code. This is an issue
if `render*` is called in a loop like in gulp-sass.

Fixes sass#1168
xzyfer added a commit to xzyfer/node-sass that referenced this issue Jun 15, 2016
The options object passed into `render` and `renderSync` is only
shallow copied. This is an issue when nested objects and arrays like
custom importer and functions. In the case of custom function we
wrap the provided function. This wrapped version replaces the provided
one which can then leak back into the calling code. This is an issue
if `render*` is called in a loop like in gulp-sass.

Fixes sass#1168
xzyfer added a commit to xzyfer/node-sass that referenced this issue Jun 15, 2016
The options object passed into `render` and `renderSync` is only
shallow copied. This is an issue when nested objects and arrays like
custom importer and functions. In the case of custom function we
wrap the provided function. This wrapped version replaces the provided
one which can then leak back into the calling code. This is an issue
if `render*` is called in a loop like in gulp-sass.

Fixes sass#1168
xzyfer added a commit to xzyfer/node-sass that referenced this issue Jun 15, 2016
The options object passed into `render` and `renderSync` is only
shallow copied. This is an issue when nested objects and arrays like
custom importer and functions. In the case of custom function we
wrap the provided function. This wrapped version replaces the provided
one which can then leak back into the calling code. This is an issue
if `render*` is called in a loop like in gulp-sass.

Fixes sass#1168
xzyfer added a commit that referenced this issue Jun 15, 2016
The options object passed into `render` and `renderSync` is only
shallow copied. This is an issue when nested objects and arrays like
custom importer and functions. In the case of custom function we
wrap the provided function. This wrapped version replaces the provided
one which can then leak back into the calling code. This is an issue
if `render*` is called in a loop like in gulp-sass.

Fixes #1168
@xzyfer
Copy link
Contributor

xzyfer commented Jun 15, 2016

This fix will be released in v3.8.0 tomorrow.

@HairyRabbit
Copy link

@xzyfer 😘
Very thanks, importer is important for me.

@xzyfer xzyfer modified the milestone: next.patch Sep 4, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants