RCTSharedApplication() delegate error react native - javascript

So I'm fairly new to react native and mobile development in general, this error keeps cropping up, the test file in question that is failing is the standard generated file provided by Facebook with a react native build.
Here's the test:
- (void)testRendersWelcomeScreen
{
UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
BOOL foundElement = NO;
__block NSString *redboxError = nil;
RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
if (level >= RCTLogLevelError) {
redboxError = message;
}
});
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
return YES;
}
return NO;
}];
}
RCTSetLogFunction(RCTDefaultLogFunction);
XCTAssertNil(redboxError, #"RedBox error: %#", redboxError);
XCTAssertTrue(foundElement, #"Couldn't find element with text '%#' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
}
And here is the error:
redacted/ios/ProjectTests/Project.m:40:29: error: bad receiver type 'int'
UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
The app seems to actually compile and work in iOS simulator so I'm not really sure what the problem is, the obvious answer could be just remove the test. However I'm interested in a possible cause, cheers.

Try reinstalling dependencies:
$ rm -rf node_modules
$ npm i
I had the same issue and it worked for me, as I had downgraded some libs in a different branch before (check: https://github.com/facebook/react-native/issues/13901).

Related

How to detect if running in the new Windows Terminal?

An upcoming feature of the Windows Terminal preview is that it has full emoji support:
Compared to:
In Node.js, how do I detect if I'm running in a terminal wrapped by the Windows Terminal instead of its "naked" variation? Is there an environmental variable I can extract or a synchronous test I can do?
You can check for the WT_SESSION environmental variable which is set to a v4 UUID: https://github.com/microsoft/terminal/issues/1040
If you're looking for a quick and dirty way to check, this should work:
!!process.env.WT_SESSION
There's also a more elaborate method you can use, taking advantage of is-uuid, is-wsl and process.platform:
import isUUID from 'is-uuid';
import isWsl from 'is-wsl';
const isWindowsTerminal = (process.platform === "win32" || isWsl) && isUUID.v4(process.env.WT_SESSION);
I prefer this approach from https://github.com/microsoft/terminal/issues/6269 (in PowerShell):
function IsWindowsTerminal ($childProcess) {
if (!$childProcess) {
return $false
} elseif ($childProcess.ProcessName -eq 'WindowsTerminal') {
return $true
} else {
return IsWindowsTerminal -childProcess $childProcess.Parent
}
}
which I then use in my profile to turn on e.g. oh-my-posh.
$IsWindowsTerminal = IsWindowsTerminal -childProcess (Get-Process -Id $PID)
if($IsWindowsTerminal) {
oh-my-posh --init --shell pwsh --config $HOME\Documents\mytheme.omp.json | Invoke-Expression
}

Build version information in Application Insights telemetry (client-side)

We have a SPA hosted on ASP.NET application. We want to track the build version of the whole app.
So this telemetry initializer
public class VersionInfoTelemetryInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
telemetry.Context.Component.Version =
typeof(Startup).Assembly.GetName().Version.ToString();
}
}
will be used in Gloabal.asax
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
var tc = TelemetryConfiguration.Active;
tc.InstrumentationKey = ConfigurationManager.AppSettings["AI Instrumentation Key"];
tc.TelemetryInitializers.Add(new VersionInfoTelemetryInitializer());
...
}
}
Server-side telemetry will have version information appended. But I am not able to do the same for the client-side telemetry. I have tried this
var appInsights = window.appInsights || function(config) {
// standard js snippet from azure portal
}({
instrumentationKey: '{{INSTRUMENTATIONKEY}}'
});
window.appInsights = appInsights;
window.appInsights.context.application.ver = 'some version number';
which results in following JS error
Uncaught TypeError: Cannot read property 'application' of undefined
I also tried
appInsights.queue.push(function () {
appInsights.context.addTelemetryInitializer(versionInfoTelemetryInitialier);
});
function versionInfoTelemetryInitialier(envelope) {
var telemetryItem = envelope.data.baseData;
telemetry.context.component.version = 'some version number';
}
which will warn with following message
AI: TelemetryInitializerFailed message:"One of telemetry initializers failed, telemetry
item will not be sent: TypeError" props:"{exception:[object Error]{ stack: 'TypeError:
Unable to get property 'component' of undefined or null reference\n at
versionInfoTelemetryInitialier (https://localhost:44301/landing/index:107:9)\n at
n.prototype._track (https://az416426.vo.msecnd.net/scripts/a/ai.0.js:1:65589)\n at
n.prototype.track...
What should I do so that client-side telemetry has version information attached.
i think your second attempt is very close. you need to do it via the queue, to make sure it occurs after all the AI scripts are actually loaded, so i think this is correct:
appInsights.queue.push(function () {
appInsights.context.addTelemetryInitializer(versionInfoTelemetryInitialier);
});
but in your initializer you switched from context.application.ver in your first example, to context.component.version in your second.
the javascript SDK is documented on the github repo:
https://github.com/Microsoft/ApplicationInsights-JS/blob/master/API-reference.md
and the examples there show:
context.application.ver: string
context.application.build : string
so shouldn't that initializer method be:
function versionInfoTelemetryInitialier(envelope) {
var telemetryItem = envelope.data.baseData;
telemetry.context.application.ver = 'some version number';
}

Work around to unsolved npm link symlink requires?

When developing an NPM package, it's common to use:
npm link
It allows to modify <myPackage> under development without the need of publishing and unpublishing all the time! The developer can make any changes locally and see it immediately.
It's installed into a project by using:
npm link <myPackage>
It's great, but there's a problem if the <myPackage> have a require(path).
It'll use the real location of <myPackage> as __dirname, for example, instead of the expected location of the symlink, that should be local to the project, like a regular node_module.
The solution I found so far, for my particular case works fine:
module.exports = {
loadImage: function (filename) {
var img
if (typeof window !== 'undefined' && ({}).toString.call(window) === '[object Window]') {
try {
img = require('../../src/images/' + filename)
} catch (e) {
// Development only
img = require('./template/src/images/' + filename)
}
} else {
img = '/assets/images/' + filename
}
return img
}
}
But as you can imagine, this cause Warning messages in the Browser.
While I'm aware of the reason why of this problem, ideally, I'd like to suppress the error.
I believe it won't be a very popular question, in that case, here's a nice option that won't cause any warning messages and that is quite specific to the NPM Package development stage.
The following modules.exports expose some code snippets you'd like to import into your application. You'll find the loadImage method, with a fallback for the require(path):
module.exports = {
loadImage: function (filename) {
if (typeof window !== 'undefined' && ({}).toString.call(window) === '[object Window]') {
return (process.env.NPM_PACKAGE_DEV && require('./template/src/images/' + filename) ||
require('./template/src/images/' + filename))
} else {
return '/assets/images/' + filename
}
},
isBrowser: function () {
return (typeof window !== 'undefined' && ({}).toString.call(window) === '[object Window]')
}
}
What's good about this, is that you can set the NPM_PACKAGE_DEV by running the command, than initialize the node server (osx terminal syntax):
export NPM_PACKAGE_DEV=1 && node server.js
If the NPM_PACKAGE_DEV is omitted, the require() fallback to the end use path, that is relative to the project node_modules directory.
Hope this helps someone else in the future!

WinRT - Starting/Registering IBackgroundTask in universal application

I would like to start my IBackgroundTask when my application starts up.
I have added my task to the .appxmanifest.xml file, and my extensions tag now looks like this
<Extensions>
<Extension Category="windows.backgroundTasks" EntryPoint="CordovaApp.Library.UploadTask">
<BackgroundTasks>
<Task Type="systemEvent" />
<Task Type="timer" />
</BackgroundTasks>
</Extension>
</Extensions>
My IBackgroundTask class is called UploadTask and is held in another project which has the outtype set to Windows Runtime Component.
Here is a cut down version of the code, so you can see the namespace etc
namespace CordovaApp.Library
{
public sealed class UploadTask : IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
var connectionProfile = NetworkInformation.GetInternetConnectionProfile();
// connectionProfile can be null (e.g. airplane mode)
if (connectionProfile != null && connectionProfile.IsWlanConnectionProfile)
{
// custom code here
}
}
}
}
I have added a reference to this project to my universal runtime component project.
Everything builds fine.
Now to start the application, i guess i have to use WinJs, so i have the following code.
var uploadTaskName = 'UploadTask';
var tasks = Windows.ApplicationModel.Background.BackgroundTaskRegistration.allTasks;
var uploadTaskFound = false;
for (var i = 0; i < tasks.length; i++) {
if (tasks[i].Value.name == uploadTaskName) {
successCallback();
return;
}
}
Windows.ApplicationModel.Background.BackgroundExecutionManager.requestAccessAsync().then(function() {
var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder();
builder.name = "Upload Task";
builder.taskEntryPoint = "CordovaApp.Library.UploadTask";
builder.setTrigger(new Windows.ApplicationModel.Background.TimeTrigger(15, false));
return builder.register();
}).done(function () {
successCallback();
}, function(err) {
errorCallback(err);
});
Now the requestAccessAsync method always throws an exception of
0x80004005 - JavaScript runtime error: Unspecified error
WinRT information: The application is not lock-screen capable.
Have a registered everything correctly? I am running this via Visual Studio 2013 on a laptop.
Seems that because the app was already installed, the permission was not given.
By uninstalling the application, and re-running it, i was then prompted to allow/disallow the background service to run. Checked allow, and now seems to work

How do I require() from the console using webpack?

How do I require() / import modules from the console? For example, say I've installed the ImmutableJS npm, I'd like to be able to use functions from the module while I'm working in the console.
Here's another more generic way of doing this.
Requiring a module by ID
The current version of WebPack exposes webpackJsonp(...), which can be used to require a module by ID:
function _requireById(id) {
return webpackJsonp([], null, [id]);
}
or in TypeScript
window['_requireById'] =
(id: number): any => window['webpackJsonp'];([], null, [id]);
The ID is visible at the top of the module in the bundled file or in the footer of the original source file served via source maps.
Requiring a module by name
Requiring a module by name is much trickier, as WebPack doesn't appear to keep any reference to the module path once it has processed all the sources. But the following code seems to do the trick in lot of the cases:
/**
* Returns a promise that resolves to the result of a case-sensitive search
* for a module or one of its exports. `makeGlobal` can be set to true
* or to the name of the window property it should be saved as.
* Example usage:
* _requireByName('jQuery', '$');
* _requireByName('Observable', true)ยด;
*/
window['_requireByName'] =
(name: string, makeGlobal?: (string|boolean)): Promise<any> =>
getAllModules()
.then((modules) => {
let returnMember;
let module = _.find<any, any>(modules, (module) => {
if (_.isObject(module.exports) && name in module.exports) {
returnMember = true;
return true;
} else if (_.isFunction(module.exports) &&
module.exports.name === name) {
return true;
}
});
if (module) {
module = returnMember ? module.exports[name] : module.exports;
if (makeGlobal) {
const moduleName = makeGlobal === true ? name : makeGlobal as string;
window[moduleName] = module;
console.log(`Module or module export saved as 'window.${moduleName}':`,
module);
} else {
console.log(`Module or module export 'name' found:`, module);
}
return module;
}
console.warn(`Module or module export '${name}'' could not be found`);
return null;
});
// Returns promise that resolves to all installed modules
function getAllModules() {
return new Promise((resolve) => {
const id = _.uniqueId('fakeModule_');
window['webpackJsonp'](
[],
{[id]: function(module, exports, __webpack_require__) {
resolve(__webpack_require__.c);
}},
[id]
);
});
}
This is quick first shot at this, so it's all up for improvement!
Including this in a module will allow require([modules], function) to be used from a browser
window['require'] = function(modules, callback) {
var modulesToRequire = modules.forEach(function(module) {
switch(module) {
case 'immutable': return require('immutable');
case 'jquery': return require('jquery');
}
})
callback.apply(this, modulesToRequire);
}
Example Usage:
require(['jquery', 'immutable'], function($, immutable) {
// immutable and $ are defined here
});
Note: Each switch-statement option should either be something this module already requires, or provided by ProvidePlugin
Sources:
Based on this answer, which can be used to add an entire folder.
Alternative method from Webpack Docs - which allows something like require.yourModule.function()
I found a way that works, for both WebPack 1 and 2. (as long as the source is non-minified)
Repo: https://github.com/Venryx/webpack-runtime-require
Install
npm install --save webpack-runtime-require
Usage
First, require the module at least once.
import "webpack-runtime-require";
It will then add a Require() function to the window object, for use in the console, or anywhere in your code.
Then just use it, like so:
let React = Require("react");
console.log("Retrieved React.Component: " + React.Component);
It's not very pretty (it uses regexes to search the module wrapper functions) or fast (takes ~50ms the first call, and ~0ms after), but both of these are perfectly fine if it's just for hack-testing in the console.
Technique
The below is a trimmed version of the source to show how it works. (see the repo for the full/latest)
var WebpackData;
webpackJsonp([],
{123456: function(module, exports, __webpack_require__) {
WebpackData = __webpack_require__;
}},
[123456]
);
var allModulesText;
var moduleIDs = {};
function GetIDForModule(name) {
if (allModulesText == null) {
let moduleWrapperFuncs = Object.keys(WebpackData.m).map(moduleID=>WebpackData.m[moduleID]);
allModulesText = moduleWrapperFuncs.map(a=>a.toString()).join("\n\n\n");
// these are examples of before and after webpack's transformation: (which the regex below finds the var-name of)
// require("react-redux-firebase") => var _reactReduxFirebase = __webpack_require__(100);
// require("./Source/MyComponent") => var _MyComponent = __webpack_require__(200);
let regex = /var ([a-zA-Z_]+) = __webpack_require__\(([0-9]+)\)/g;
let matches = [];
let match;
while (match = regex.exec(allModulesText))
matches.push(match);
for (let [_, varName, id] of matches) {
// these are examples of before and after the below regex's transformation:
// _reactReduxFirebase => react-redux-firebase
// _MyComponent => my-component
// _MyComponent_New => my-component-new
// _JSONHelper => json-helper
let moduleName = varName
.replace(/^_/g, "") // remove starting "_"
.replace(new RegExp( // convert chars where:
"([^_])" // is preceded by a non-underscore char
+ "[A-Z]" // is a capital-letter
+ "([^A-Z_])", // is followed by a non-capital-letter, non-underscore char
"g"),
str=>str[0] + "-" + str[1] + str[2] // to: "-" + char
)
.replace(/_/g, "-") // convert all "_" to "-"
.toLowerCase(); // convert all letters to lowercase
moduleIDs[moduleName] = parseInt(id);
}
}
return moduleIDs[name];
}
function Require(name) {
let id = GetIDForModule(name);
return WebpackData.c[id].exports;
}
Being able to use require modules in the console is handy for debugging and code analysis. #psimyn's answer is very specific so you aren't likely to maintain that function with all the modules you might need.
When I need one of my own modules for this purpose, I assign a window property to it so I can get at it e.g window.mymodule = whatever_im_exporting;. I use the same trick to expose a system module if I want to play with it e.g:
myservice.js:
let $ = require('jquery');
let myService = {};
// local functions service props etc...
module.exports = myService;
// todo: remove these window prop assignments when done playing in console
window.$ = $;
window.myService = myService;
It is still a bit of a pain, but digging into the bundles, I can't see any way to conveniently map over modules.
The answer from #Rene Hamburger is good but unfortunately doesn't work anymore (at least with my webpack version). So I updated it:
function getWebpackInternals() {
return new Promise((resolve) => {
const id = 'fakeId' + Math.random();
window['webpackJsonp'].push(["web", {
[id]: function(module, __webpack_exports__, __webpack_require__) {
resolve([module, __webpack_exports__, __webpack_require__])
}
},[[id]]]);
});
}
function getModuleByExportName(moduleName) {
return getWebpackInternals().then(([_, __webpack_exports__, __webpack_require__]) => {
const modules = __webpack_require__.c;
const moduleFound = Object.values(modules).find(module => {
if (module && module.exports && module.exports[moduleName]) return true;
});
if (!moduleFound) {
console.log('couldnt find module ' + moduleName);
return;
}
return moduleFound.exports[moduleName];
})
}
getModuleByExportName('ExportedClassOfModule');
expose-loader is, in my opinion, a more elegant solution:
require("expose-loader?libraryName!./file.js");
// Exposes the exports for file.js to the global context on property "libraryName".
// In web browsers, window.libraryName is then available.
Adding the below code to one of your modules will allow you to load modules by id.
window.require = __webpack_require__;
In the console use the following:
require(34)
You could do something similar as psimyn advised by
adding following code to some module in bundle:
require.ensure([], function () {
window.require = function (module) {
return require(module);
};
});
Use require from console:
require("./app").doSomething();
See more
After making an npm module for this (see my other answer), I did a search on npms.io and seem to have found an existing webpack-plugin available for this purpose.
Repo: https://www.npmjs.com/package/webpack-expose-require-plugin
Install
npm install --save webpack-expose-require-plugin
Usage
Add the plugin to your webpack config, then use at runtime like so:
let MyComponent = require.main("./path/to/MyComponent");
console.log("Retrieved MyComponent: " + MyComponent);
See package/repo readme page for more info.
EDIT
I tried the plugin out in my own project, but couldn't get it to work; I kept getting the error: Cannot read property 'resource' of undefined. I'll leave it here in case it works for other people, though. (I'm currently using the solution mentioned above instead)
After both making my own npm package for this (see here), as well as finding an existing one (see here), I also found a way to do it in one-line just using the built-in webpack functions.
It uses WebPack "contexts": https://webpack.github.io/docs/context.html
Just add the following line to a file directly in your "Source" folder:
window.Require = require.context("./", true, /\.js$/);
Now you can use it (eg. in the console) like so:
let MyComponent = Require("./Path/To/MyComponent");
console.log("Retrieved MyComponent: " + MyComponent);
However, one important drawback of this approach, as compared to the two solutions mentioned above, is that it seems to not work for files in the node_modules folder. When the path is adjusted to "../", webpack fails to compile -- at least in my project. (perhaps because the node_modules folder is just so massive)

Categories

Resources