moving from vu2 to vue 3 - google-chrome

I have started the migration process from vue2 to vue3. And now I have such a problem: the browser console shows some kind of warning and it is generated approximately 1000 times in 1 second. this causes the tab to hang. How can it be stopped?

setup() {
// your reactive properties
const rProp = ref('ref prop');
return {
// setup returns object that used by template for rendering
// if prop is absent you will see the warnings
rProp
}
}

Related

Audio distortion occurs when using AudioWorkletProcessor with a MediaStream source and connecting a bluetooth device while it is already running

In our project, we use AudioContext to wire up input from a microphone to an AudioWorkletProcessor and out to a MediaStream. Ultimately, this is sent to other peers in a WebRTC call.
If someone loads the page, the audio always sounds fine. But if they connect with a hard-wired microphone like a laptop mic or webcam, then connect a bluetooth device (such as airpods or headphones), then the audio becomes distorted & robotic sounding.
If we tear out all the other code and simplify it, we still have the issue.
bypassProcessor.js
// Basic processor that wires input to output without transforming the data
// https://github.com/GoogleChromeLabs/web-audio-samples/blob/main/audio-worklet/basic/hello-audio-worklet/bypass-processor.js
class BypassProcessor extends AudioWorkletProcessor {
process(inputs, outputs) {
const input = inputs[0];
const output = outputs[0];
for (let channel = 0; channel < output.length; ++channel) {
output[channel].set(input[channel]);
}
return true;
}
}
registerProcessor('bypass-processor', BypassProcessor);
main.js
const microphoneStream = await navigator.mediaDevices.getUserMedia({
audio: true, // have also tried { channelCount: 1 } and { channelCount: { exact: 1 } }
video: false
})
const audioCtx = new AudioContext()
const inputNode = audioCtx.createMediaStreamSource(microphoneStream)
await audioCtx.audioWorklet.addModule('worklet/bypassProcessor.js')
const processorNode = new AudioWorkletNode(audioCtx, 'bypass-processor')
inputNode.connect(processorNode).connect(audioCtx.destination)
Interestingly, I have found if you comment out the 2 audio worklet lines and instead create a simple gain node, then it works fine.
// await audioCtx.audioWorklet.addModule('worklet/bypassProcessor.js')
// const processorNode = new AudioWorkletNode(audioCtx, 'bypass-processor')
const gainNode = audioCtx.createGain()
Also if you simply create the AudioWorkletNode, but don't even connect it to the others, this also reproduces the issue.
I've created a small React app here that reproduces the problem: https://github.com/JacobMuchow/audio_distortion_repro/tree/master
I've tried some options such as detecting when this happens using 'ondevicechange' event, closing the old AudioContext & nodes and recreating everything, but this only works some of the time. If I wait for some time and then recreate it again, it works so I'm worried about some type of garbage collection issue with the processor when attempting this, but that might be beside the point.
I suspect this has something to do with sample rates... when the AudioContext is correctly recreated it switches from 48 kHz to 16 kHz and then it sounds find. But sometimes it is recreated with 48 kHz still and it continues to sound robotic.
Threads on the internet concerning this are incredibly sparse and I'm hoping someone has specific experience with this issue or this API and can point out what I need to do differently.
For Chrome, the problem is very likely https://crbug.com/1090441 that was recently fixed. I think Firefox doesn't have this problem but I didn't check.

How do you use getHtmlPrintDocumentSourceAsync to print in HTML/JavaScript Windows Store apps?

I am very simply trying to print some content in a Windows 10 app (Universal) using HTML and JavaScript/WinJS.
ALL of the documentation says that there is a function on MSApp called getHtmlPrintDocumentSource.
I do not have this, nor can I seem to find any relevant source to see if it may have been moved. I instead have getHtmlPrintDocumentSourceAsync. This seems to be a replacement for the former, but I cannot get it to work and there is zero documentation on it as far as I can tell.
When I run the below code (which is based on the documentation but updated to be async):
function onPrintTaskRequested(printEvent) {
var printTask = printEvent.request.createPrintTask("Print Sample", function (args) {
MSApp.getHtmlPrintDocumentSourceAsync(document)
.then(function(result) {
args.setSource(result);
});
printTask.oncompleted = onPrintTaskCompleted;
});
}
result is populated with some of the print settings as I would expect, but the content property is set to 0, which I am guessing is the problem. I can't really be sure as there is no documentation for this function. I can't even run any of the dozens of pieces of example code in the documentation using `getHtmlPrintDocumentSource' because it seemingly doesn't exist anymore.
In addition to just sending document to the Async method, I have tried a couple of different variations of creating document fragments. Same results.
Probably not terribly helpful, but the message in the Windows Print Dialog that opens when executing the above code is: "Nothing was sent to print. Open a document and print again."
Any ideas?
getHtmlPrintDocumentSource is a synchronous deprecated API in Windows 10 apps. We'll work on some of the docs left behind for Windows 8 and 8.1 to clarify that.
Check out https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/Printing/js for an example of how to use getHtmlPrintDocumentSourceAsync in JavaScript.
Here is the code:
// Needs to be invoked before calling the print API
function registerForPrintContract() {
var printManager = Windows.Graphics.Printing.PrintManager.getForCurrentView();
printManager.onprinttaskrequested = onPrintTaskRequested;
console.log("Print Contract registered. Use the Print button to print.", "sample", "status");
}
// Variable to hold the document source to print
var gHtmlPrintDocumentSource = null;
// Print event handler for printing via the PrintManager API.
function onPrintTaskRequested(printEvent) {
var printTask = printEvent.request.createPrintTask("Print Sample", function (args) {
args.setSource(gHtmlPrintDocumentSource);
// Register the handler for print task completion event
printTask.oncompleted = onPrintTaskCompleted;
});
}
// Print Task event handler is invoked when the print job is completed.
function onPrintTaskCompleted(printTaskCompletionEvent) {
// Notify the user about the failure
if (printTaskCompletionEvent.completion === Windows.Graphics.Printing.PrintTaskCompletion.failed) {
console.log("Failed to print.", "sample", "error");
}
}
// Executed just before printing.
var beforePrint = function () {
// Replace with code to be executed just before printing the current document:
};
// Executed immediately after printing.
var afterPrint = function () {
// Replace with code to be executed immediately after printing the current document:
};
function printButtonHandler() {
// Optionally, functions to be executed immediately before and after printing can be configured as following:
window.document.body.onbeforeprint = beforePrint;
window.document.body.onafterprint = afterPrint;
// Get document source to print
MSApp.getHtmlPrintDocumentSourceAsync(document).then(function (htmlPrintDocumentSource) {
gHtmlPrintDocumentSource = htmlPrintDocumentSource;
// If the print contract is registered, the print experience is invoked.
Windows.Graphics.Printing.PrintManager.showPrintUIAsync();
});
}

chrome.storage.sync vs chrome.storage.local

I was trying to understand how to use the chrome.storage.api.
I have included the following in my manifest.json:
"permissions": [
"activeTab","storage"
],
Than, I opened a new tab with the devtools and switched the <page context> to the one of my chrome-extension. Than I typed:
chrome.storage.sync.set({"foo":"bar"},function(){ console.log("saved ok"); } );
and got:
undefined
saved ok
Than I tried getting this stored value:
chrome.storage.sync.get("foo",function(data){ console.log(data); } );
but this got me:
undefined
Object {}
Than I did the same, but instead of sync I used local and this worked as expected:
chrome.storage.local.set({"foo":"bar"},function(){ console.log("saved ok"); } );
..and the retrieval:
chrome.storage.local.get("foo",function(data){ console.log(data); } );
Which got me: Object {foo: "bar"} as it should.
Is this because I am not signed in to my account on chrome? But in that case, isn't chrome.storage.sync designed to fallback into storing the data locally?
EDIT
Strangely, when i type this straight on console it seems to be working, but this code doesn't run from background.js code inside a click listener:
var dataCache = {};
function addStarredPost(post)
{
var id = getPostId(post);
var timeStamp = new Date().getTime();
var user = getUserName();
dataCache[id] = {"id":id,"post":post,"time":timeStamp,"user":user};
chrome.storage.sync.set(dataCache,function(){ console.log("Starred!");});
}
After this is ran, chrome.storage.sync.get(null,function(data){ console.log(data); }); returns an empty object as if the data wasn't stored. :/
This code seems to be working perfect with chrome.storage.local instead.
chrome.runtime.lastErros returns undefined
The max size for chrome local storage is 5,242,880 bytes.
To extend the storage you can add on the manifest.json :
"permissions": [
"unlimitedStorage"
]
The max size for chrome sync storage is:
102,400 bytes total
8,192 bytes per item
512 items max
1,800 write operations per hour
120 operations per minutes
(source)
Whoops!
The problem was I was trying to sync data that exceeded in size. (4096 Bytes per item)
I wasn't getting chrome.runtime.lastError because I was mistakenly putting it inside the get function scope, instead of the set function which was producing the error. Hence, I'm posting this answer so it might help others who share the same confusion.
You should check chrome.runtime.lastError inside each api call, like so:
chrome.storage.local.set(objectToStore, function(data)
{
if(chrome.runtime.lastError)
{
/* error */
console.log(chrome.runtime.lastError.message);
return;
}
//all good. do your thing..
}
This ran OK with chrome.storage.local because according to the docs you only have this limitation with sync.
printing chrome.runtime.lastError gave me: Object {message: "QUOTA_BYTES_PER_ITEM quota exceeded"}

How to solve that AttachAsync of a DownloadOperation does not return immediately?

When using the Background Transfer API we must iterate through current data transfers to start them again ahen the App restarts after a termination (i.e. system shutdown). To get progress information and to be able to cancel the data transfers they must be attached using AttachAsync.
My problem is that AttachAsync only returns when the data transfer is finished. That makes sense in some scenarios. But when having multiple data transfers the next transfer in the list would not be started until the currently attached is finished. My solution to this problem was to handle the Task that AttachAsync().AsTask() returns in the classic way (not use await but continuations):
IReadOnlyList<DownloadOperation> currentDownloads =
await BackgroundDownloader.GetCurrentDownloadsAsync();
foreach (var downloadOperation in currentDownloads)
{
Task task = downloadOperation.AttachAsync().AsTask();
DownloadOperation operation = downloadOperation;
task.ContinueWith(_ =>
{
// Handle success
...
}, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.FromCurrentSynchronizationContext());
task.ContinueWith(_ =>
{
// Handle cancellation
...
}, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled,
TaskScheduler.FromCurrentSynchronizationContext());
task.ContinueWith(t =>
{
// Handle errors
...
}, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.FromCurrentSynchronizationContext());
}
It kind of works (in the actual code I add the downloads to a ListBox). The loop iterates through all downloads and executes StartAsync. But the downloads are not really started all at the same time. Only one is runninng at a time and only if it finishes the next one continues.
Any solution for this problem?
The whole point of Task is to allow you to have the option of parallel operations. If you await then you are telling the code to serialize the operations; if you don't await, then you are telling the code to parallelize.
What you can do is add each download task to a list, telling the code to parallelize. You can then wait for tasks to finish, one by one.
How about something like:
IReadOnlyList<DownloadOperation> currentDownloads =
await BackgroundDownloader.GetCurrentDownloadsAsync();
if (currentDownloads.Count > 0)
{
List<Task<DownloadOperation>> tasks = new List<Task<DownloadOperation>>();
foreach (DownloadOperation downloadOperation in currentDownloads)
{
// Attach progress and completion handlers without waiting for completion
tasks.Add(downloadOperation.AttachAsync().AsTask());
}
while (tasks.Count > 0)
{
// wait for ANY download task to finish
Task<DownloadOperation> task = await Task.WhenAny<DownloadOperation>(tasks);
tasks.Remove(task);
// process the completed task...
if (task.IsCanceled)
{
// handle cancel
}
else if (task.IsFaulted)
{
// handle exception
}
else if (task.IsCompleted)
{
DownloadOperation dl = task.Result;
// handle completion (e.g. add to your listbox)
}
else
{
// should never get here....
}
}
}
I hope this is not too late but I know exactly what you are talking about. I'm also trying to resume all downloads when the application starts.
After hours of trying, here's the solution that works.
The trick is to let the download operation resume first before attacking the progress handler.
downloadOperation.Resume();
await downloadOperation.AttachAsync().AsTask(cts.Token);

RX throttle on WinRT TemplatedControl

I have some problems with thread synchronization in my Templated control (trying to do a AutoComplete control)
Inside my control I have this code:
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
var searchTextBox = GetTemplateChild("SearchTextBox") as TextBox;
if (searchTextBox != null)
{
var searchDelegate = SearchAsync;
Observable.FromEventPattern(searchTextBox, "TextChanged")
.Select(keyup => searchTextBox.Text)
.Where(TextIsLongEnough)
.Throttle(TimeSpan.FromMilliseconds(500))
.Do(ShowProgressBar)
.SelectMany(searchDelegate)
.ObserveOn(Dispatcher)
.Subscribe(async results => await RunOnDispatcher(() =>
{
IsInProgress = false;
SearchResults.Clear();
foreach (var result in results)
{
SearchResults.Add(result);
}
}));
}
}
And it is complaining that inside my ShowProgressBar method I'm trying to access code that was marshalled by another thread.
If I comment out the Throttle and the ObserveOn(Dispatcher) it works just fine, but it does not throttle my service calls as I want to.
If I only comment out the Throttle part, Nothing happens at all.
Asti's got the right idea, but a far better approach would be to provide the IScheduler argument to Throttle instead:
// NB: Too lazy to look up real name
.Throttle(TimeSpan.FromMilliseconds(500), CoreDispatcherScheduler.Instance)
This will make operations below it happen on the UI thread (including your ShowProgressBar), up until the SelectMany.
Every dependency object requires that any changes to dependency properties be made only on the Dispatcher thread. The Throttle is using a different scheduler, hence making any changes to the UI in a subsequent Do combinator would result in an access exception.
You can resolve this by:
Add an ObserveOnDispatcher before any actions which cause side-effects on the Dispatcher. Optionally use another scheduler down the pipeline.
Use Dispatcher.Invoke to execute side-effects through the dispatcher. E.g., .Do(() => Dispatcher.Invoke(new Action(ShowProgressBar)))