diff --git a/assets/browser-fetch.js.t b/assets/browser-fetch.js.t index 5880b1ab..d762e0cd 100644 --- a/assets/browser-fetch.js.t +++ b/assets/browser-fetch.js.t @@ -2,6 +2,7 @@ define('fetch', ['exports'], function(self) { 'use strict'; var Promise = global.Ember.RSVP.Promise; + var window = self; if (global.FormData) { self.FormData = global.FormData; } @@ -17,6 +18,9 @@ if (global.Symbol) { self.Symbol = global.Symbol; } + if (global.URLSearchParams) { + self.URLSearchParams = global.URLSearchParams; + } <%= moduleBody %> @@ -45,10 +49,6 @@ } else { self['default'] = self.fetch; } - - self['Headers'] = self.Headers; - self['Request'] = self.Request; - self['Response'] = self.Response; }); define('fetch/ajax', ['exports'], function() { diff --git a/index.js b/index.js index 8511fb61..c3107ec3 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,23 @@ 'use strict'; var path = require('path'); -var map = require('broccoli-stew').map; +// We use a few different Broccoli plugins to build our trees: +// +// broccoli-templater: renders the contents of a file inside a template. +// Used to wrap the browser polyfill in a shim that prevents it from exporting +// a global. +// +// broccoli-stew: super useful library of Broccoli utilities. We use: +// +// * find - finds files in a tree based on a glob pattern +// * map - map content of files in a tree +// +var stew = require('broccoli-stew'); +var Template = require('broccoli-templater'); +var MergeTrees = require('broccoli-merge-trees'); +var concat = require('broccoli-concat'); +var map = stew.map; +var find = stew.find; /* * The `index.js` file is the main entry point for all Ember CLI addons. The @@ -93,60 +109,33 @@ module.exports = { } }; - -// We use a few different Broccoli plugins to build our trees: -// -// broccoli-templater: renders the contents of a file inside a template. -// Used to wrap the browser polyfill in a shim that prevents it from exporting -// a global. -// -// broccoli-funnel: used to import a stub file that requires the node package -// when running in FastBoot. -// -// broccoli-stew: super useful library of Broccoli utilities. We use: -// -// * rename - renames files in a tree -// * find - finds files in a tree based on a glob pattern - -var Template = require('broccoli-templater'); -var stew = require('broccoli-stew'); -var rename = stew.rename; -var find = stew.find; - // Path to the template that contains the shim wrapper around the browser // polyfill var templatePath = path.resolve(__dirname + '/assets/browser-fetch.js.t'); -// Returns a tree containing the browser polyfill (from -// `node_modules/whatwg-fetch`), wrapped in a shim that stops it from exporting -// a global and instead turns it into a module that can be used by the Ember -// app. +// Returns a tree containing the browser polyfill (from `yetch` and `abortcontroller-polyfill`), +// wrapped in a shim that stops it from exporting a global and instead turns it into a module +// that can be used by the Ember app. function treeForBrowserFetch() { - var fetchPath = require.resolve('whatwg-fetch'); - var expandedFetchPath = expand(fetchPath); + var fetchPath = require.resolve('yetch/polyfill'); + var abortcontrollerPath = require.resolve('abortcontroller-polyfill'); - var fetch = normalizeFileName(find(expandedFetchPath)); + var expandedFetchPath = expand(fetchPath, 'dist/yetch-polyfill.js'); + var expandedAbortcontrollerPath = expand(abortcontrollerPath, 'abortcontroller-polyfill-only.js'); + + var polyfillTree = concat(new MergeTrees([find(expandedFetchPath), find(expandedAbortcontrollerPath)]), { + outputFile: 'ember-fetch.js' + }); - return new Template(fetch, templatePath, function(content) { + return new Template(polyfillTree, templatePath, function(content) { return { moduleBody: content }; }); } -// Renames either `fastboot-fetch.js` or `whatwg-fetch/fetch.js` to just -// `ember-fetch.js`. Note that this function will rename _every_ file in the tree; -// we just happen to know that the passed tree only contains a single file. -function normalizeFileName(tree) { - return rename(tree, function() { - return 'ember-fetch.js'; - }); -} - -function expand(input) { +function expand(input, file) { var dirname = path.dirname(input); - var file = path.basename(input); - - return dirname + '/{' + file + '}'; + return path.join(dirname, file); } diff --git a/package.json b/package.json index 6751770d..82a26116 100644 --- a/package.json +++ b/package.json @@ -19,12 +19,14 @@ "test": "ember try:each" }, "dependencies": { - "broccoli-funnel": "^1.2.0", + "abortcontroller-polyfill": "^1.1.9", + "broccoli-concat": "^3.2.2", + "broccoli-merge-trees": "^2.0.0", "broccoli-stew": "^1.4.2", "broccoli-templater": "^1.0.0", "ember-cli-babel": "^6.8.2", "node-fetch": "^2.0.0-alpha.9", - "whatwg-fetch": "^2.0.3" + "yetch": "^0.0.1" }, "devDependencies": { "broccoli-asset-rev": "^2.4.5", @@ -55,7 +57,8 @@ "ember-addon": { "configPath": "tests/dummy/config", "fastbootDependencies": [ - "node-fetch" + "node-fetch", + "abortcontroller-polyfill" ] } } diff --git a/public/fastboot-fetch.js b/public/fastboot-fetch.js index 87b1c16e..32869eef 100644 --- a/public/fastboot-fetch.js +++ b/public/fastboot-fetch.js @@ -1,10 +1,20 @@ +/* globals define FastBoot */ (function() { define('fetch', ['exports'], function(self) { - var fetch = FastBoot.require('node-fetch'); - self['default'] = fetch; - self['Headers'] = fetch.Headers; - self['Request'] = fetch.Request; - self['Response'] = fetch.Response; + var AbortControllerPolyfill = FastBoot.require('abortcontroller-polyfill/dist/cjs-ponyfill'); + var nodeFetch = FastBoot.require('node-fetch'); + var abortableFetch = AbortControllerPolyfill.abortableFetch({ + fetch: nodeFetch, + Request: nodeFetch.Request + }); + + self['default'] = abortableFetch.fetch; + self['Request'] = abortableFetch.Request; + + self['Headers'] = nodeFetch.Headers; + self['Response'] = nodeFetch.Response; + + self['AbortController'] = AbortControllerPolyfill.AbortController; }); define('fetch/ajax', ['exports'], function() { diff --git a/tests/unit/abortcontroller-test.js b/tests/unit/abortcontroller-test.js new file mode 100644 index 00000000..1398582d --- /dev/null +++ b/tests/unit/abortcontroller-test.js @@ -0,0 +1,18 @@ +import { module, test } from 'qunit'; +import { AbortController } from 'fetch'; + +module('AbortController', function() { + test('signal', function(assert) { + assert.expect(1); + let controller = new AbortController(); + let signal = controller.signal; + + let done = assert.async(); + signal.addEventListener('abort', function() { + assert.ok(true); + done(); + }); + + controller.abort(); + }) +}); diff --git a/yarn.lock b/yarn.lock index 80b9d5a6..74a410bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28,6 +28,10 @@ abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" +abortcontroller-polyfill@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.1.9.tgz#9fefe359fda2e9e0932dc85e6106453ac393b2da" + accepts@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" @@ -6557,10 +6561,6 @@ websocket-extensions@>=0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.1.tgz#76899499c184b6ef754377c2dbb0cd6cb55d29e7" -whatwg-fetch@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" - which@^1.2.12, which@^1.2.14, which@^1.2.9: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" @@ -6660,3 +6660,7 @@ yargs@~3.10.0: yeast@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" + +yetch@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/yetch/-/yetch-0.0.1.tgz#76f1729b2c2c667e23c3c2da90472a4897eca004"