diff --git a/README.md b/README.md
index 531be9f..cacaf3e 100644
--- a/README.md
+++ b/README.md
@@ -36,9 +36,7 @@ assert.deepEqual([...matchAll(str, globalRegex)], [
 	Object.assign(['c'], { index: 3, input: str, groups: undefined }),
 ]);
 
-assert.deepEqual([...matchAll(str, nonGlobalRegex)], [
-	Object.assign(['b'], { index: 2, input: str, groups: undefined }),
-]);
+assert.throws(() => matchAll(str, nonGlobalRegex)); // non-global regexes throw
 
 matchAll.shim(); // will be a no-op if not needed
 
@@ -54,9 +52,7 @@ assert.deepEqual([...str.matchAll(globalRegex)], [
 	Object.assign(['c'], { index: 3, input: str, groups: undefined }),
 ]);
 
-assert.deepEqual([...str.matchAll(nonGlobalRegex)], [
-	Object.assign(['b'], { index: 2, input: str, groups: undefined }),
-]);
+assert.throws(() => matchAll(str, nonGlobalRegex)); // non-global regexes throw
 
 ```
 
diff --git a/implementation.js b/implementation.js
index 78aa822..fb21929 100644
--- a/implementation.js
+++ b/implementation.js
@@ -1,7 +1,11 @@
 'use strict';
 
 var ES = require('es-abstract/es2019');
+var callBound = require('es-abstract/helpers/callBound');
 var hasSymbols = require('has-symbols')();
+var flagsGetter = require('regexp.prototype.flags');
+
+var $indexOf = callBound('String.prototype.indexOf');
 
 var regexpMatchAllPolyfill = require('./polyfill-regexp-matchall');
 
@@ -24,6 +28,16 @@ module.exports = function matchAll(regexp) {
 	var O = ES.RequireObjectCoercible(this);
 
 	if (typeof regexp !== 'undefined' && regexp !== null) {
+		var isRegExp = ES.IsRegExp(regexp);
+		if (isRegExp) {
+			// workaround for older engines that lack RegExp.prototype.flags
+			var flags = 'flags' in regexp ? ES.Get(regexp, 'flags') : flagsGetter(regexp);
+			ES.RequireObjectCoercible(flags);
+			if ($indexOf(ES.ToString(flags), 'g') < 0) {
+				throw new TypeError('matchAll requires a non-global regular expression');
+			}
+		}
+
 		var matcher = getMatcher(regexp);
 		if (typeof matcher !== 'undefined') {
 			return ES.Call(matcher, regexp, [O]);
diff --git a/polyfill.js b/polyfill.js
index ad520f5..c9e0df4 100644
--- a/polyfill.js
+++ b/polyfill.js
@@ -3,5 +3,12 @@
 var implementation = require('./implementation');
 
 module.exports = function getPolyfill() {
-	return String.prototype.matchAll || implementation;
+	if (String.prototype.matchAll) {
+		try {
+			''.matchAll(RegExp.prototype);
+		} catch (e) {
+			return String.prototype.matchAll;
+		}
+	}
+	return implementation;
 };
diff --git a/test/tests.js b/test/tests.js
index 8adc0aa..7214b47 100644
--- a/test/tests.js
+++ b/test/tests.js
@@ -110,14 +110,13 @@ module.exports = function (matchAll, regexMatchAll, t) {
 			var str = 'aabc';
 			var regex = /[ac]/g;
 			if (define.supportsDescriptors) {
-				Object.defineProperty(regex, 'flags', { value: '' });
+				Object.defineProperty(regex, 'flags', { value: undefined });
 			}
-			s2t.equal(regex.flags, '', 'regex has an empty string "flags" property');
-			var expectedResults = [
-				{ value: assign(['a'], groups({ index: 0, input: str })), done: false },
-				{ value: undefined, done: true }
-			];
-			testResults(s2t, matchAll(str, regex), expectedResults);
+			s2t.equal(regex.flags, undefined, 'regex has an undefined "flags" property');
+			s2t['throws'](
+				function () { matchAll(str, regex); },
+				'undefined flags throws'
+			);
 			s2t.end();
 		});
 
@@ -156,11 +155,25 @@ module.exports = function (matchAll, regexMatchAll, t) {
 			s2t.end();
 		});
 
-		st.test('works with a non-global non-sticky regex', function (s2t) {
+		st.test('throws with a non-global regex', function (s2t) {
 			var str = 'AaBbCc';
 			var regex = /[bc]/i;
+			s2t['throws'](
+				function () { matchAll(str, regex); },
+				TypeError,
+				'a non-global regex throws'
+			);
+			s2t.end();
+		});
+
+		st.test('works with a global non-sticky regex', function (s2t) {
+			var str = 'AaBbCc';
+			var regex = /[bc]/gi;
 			var expectedResults = [
 				{ value: assign(['B'], groups({ index: 2, input: str })), done: false },
+				{ value: assign(['b'], groups({ index: 3, input: str })), done: false },
+				{ value: assign(['C'], groups({ index: 4, input: str })), done: false },
+				{ value: assign(['c'], groups({ index: 5, input: str })), done: false },
 				{ value: undefined, done: true }
 			];
 			testResults(s2t, matchAll(str, regex), expectedResults);
@@ -205,17 +218,27 @@ module.exports = function (matchAll, regexMatchAll, t) {
 			var expectedResults = [
 				{ value: undefined, done: true }
 			];
+
+			/* eslint no-invalid-regexp: [2, { "allowConstructorFlags": ["y"] }] */
+			var regex = new RegExp('\\B', 'y');
+			s2t['throws'](
+				function () { matchAll(str, regex); },
+				TypeError,
+				'non-global sticky regex throws'
+			);
+
 			/* eslint no-invalid-regexp: [2, { "allowConstructorFlags": ["y"] }] */
-			testResults(s2t, matchAll(str, new RegExp('\\B', 'y')), expectedResults);
+			testResults(s2t, matchAll(str, new RegExp('\\B', 'gy')), expectedResults);
+
 			s2t.end();
 		});
 
 		st.test('unflagged', function (s2t) {
-			var expectedResults = [
-				{ value: assign([''], groups({ index: 1, input: str })), done: false },
-				{ value: undefined, done: true }
-			];
-			testResults(s2t, matchAll(str, /\B/), expectedResults);
+			s2t['throws'](
+				function () { matchAll(str, /\B/); },
+				TypeError,
+				'unflagged regex throws'
+			);
 			s2t.end();
 		});