Closed dofirfauzi closed 10 months ago
Can you reproduce this issue on the demo page?
I want to leave some thoughts here.
vue-qrcode-reader
uses @sec-ant/barcode-detector
as a polyfill of the Barcode Detection API. However the @sec-ant/barcode-detector
package runs in a non-intrusive way:
globalThis.BarcodeDetector ??= BarcodeDetector;
So if there's a BarcodeDetector
already defined in the global, the polyfill won't kick in.
Per the compatibility table on MDN, BarcodeDetector
is fully supported on Chrome Android and not supported on Safari Desktop at all. So the polyfill is not needed in the former and is fully functional in the latter. However BarcodeDetector
is partially supported on Chrome Desktop in a macOS system, so the polyfill in this case won't work and the browser native implementation is used. And this error is probably caused by the native implementation not supporting videos as input or sth like that.
But I have to say I don't have a macOS device and I'm not familiar with the vue-qrcode-reader
code base, so I cannot say for sure this is the problem.
If this is true, the recent versions of @sec-ant/barcode-detector
provide a subpath
import which acts as a pure module. So you can explicitly import the polyfilled BarcodeDetector
like this:
import { BarcodeDetector } from "@sec-ant/barcode-detector/pure";
And also override the native one explicitly:
globalThis.BarcodeDetector = BarcodeDetector;
Can you reproduce this issue on the demo page?
I try on same browser and device, chrome on mac os, there is no error on demo page. but on my app the scanner return error on vue-qrcode-reader.js line 2091
var Mi = async (n, {
detectHandler: a,
locateHandler: o,
minDelay: u
}) => {
const d = new BarcodeDetector({ formats: ["qr_code"] }), p = (m) => async (w) => {
if (n.readyState > 1) {
const { lastScanned: S, contentBefore: v, lastScanHadContent: b } = m;
if (w - S < u)
window.requestAnimationFrame(p(m));
else {
const $ = await d.detect(n), C = $.some((F) => !v.includes(F.rawValue));
C && a($);
const E = $.length > 0;
E && o($), !E && b && o($);
const A = {
lastScanned: w,
lastScanHadContent: E,
// It can happen that a QR code is constantly in view of the camera but
// maybe a scanned frame is a bit blurry and we detect nothing but in the
// next frame we detect the code again. We also want to avoid emitting
// a `detect` event in such a case. So we don't reset `contentBefore`,
// if we detect nothing, only if we detect something new.
contentBefore: C ? $.map((F) => F.rawValue) : v
};
window.requestAnimationFrame(p(A));
}
}
};
p({
lastScanned: performance.now(),
contentBefore: [],
lastScanHadContent: false
})(performance.now());
};
I want to leave some thoughts here.
vue-qrcode-reader
uses@sec-ant/barcode-detector
as a polyfill of the Barcode Detection API. However the@sec-ant/barcode-detector
package runs in a non-intrusive way:globalThis.BarcodeDetector ??= BarcodeDetector;
So if there's a
BarcodeDetector
already defined in the global, the polyfill won't kick in.Per the compatibility table on MDN,
BarcodeDetector
is fully supported on Chrome Android and not supported on Safari Desktop at all. So the polyfill is not needed in the former and is fully functional in the latter. HoweverBarcodeDetector
is partially supported on Chrome Desktop in a macOS system, so the polyfill in this case won't work and the browser native implementation is used. And this error is probably caused by the native implementation not supporting videos as input or sth like that.But I have to say I don't have a macOS device and I'm not familiar with the
vue-qrcode-reader
code base, so I cannot say for sure this is the problem.If this is true, the recent versions of
@sec-ant/barcode-detector
provide asubpath
import which acts as a pure module. So you can explicitly import the polyfilledBarcodeDetector
like this:import { BarcodeDetector } from "@sec-ant/barcode-detector/pure";
And also override the native one explicitly:
globalThis.BarcodeDetector = BarcodeDetector;
thanks @Sec-ant ,, your solution is work
However BarcodeDetector is partially supported on Chrome Desktop in a macOS system, so the polyfill in this case won't work and the browser native implementation is used. And this error is probably caused by the native implementation not supporting videos as input or sth like that.
@Sec-ant thanks a lot. Let's follow your suggestion here also ( PR: #355 )
alright closing this then
Describe the bug I try on chrome mobile device and safari desktop there is no error and work properly but scanner error on google chrome desktop. return error Uncaught (in promise) vue-qrcode-reader.js:2091 Uncaught (in promise) (in promise) DOMException: Failed to execute 'detect' on 'BarcodeDetector': Invalid element or state
Desktop (please complete the following information):
My Code Like This