-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: fix crash due to invalid component reference
- Loading branch information
Showing
14 changed files
with
305 additions
and
190 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#include "SLKeyExtractor.h" | ||
|
||
namespace facebook::react { | ||
|
||
std::optional<std::string> SLKeyExtractor::extractKey(const std::string& input) { | ||
if (input.length() < 4) { | ||
return std::nullopt; | ||
} | ||
|
||
if (input.substr(0, 2) != "{{" || input.substr(input.length() - 2) != "}}") { | ||
return std::nullopt; | ||
} | ||
|
||
std::string key = input.substr(2, input.length() - 4); | ||
|
||
if (key.find('{') != std::string::npos || key.find('}') != std::string::npos) { | ||
return std::nullopt; | ||
} | ||
|
||
if (key.empty()) { | ||
return std::nullopt; | ||
} | ||
|
||
return key; | ||
} | ||
|
||
std::vector<std::string> SLKeyExtractor::extractAllKeys(const std::string& input) { | ||
std::vector<std::string> keys; | ||
size_t pos = 0; | ||
|
||
while (pos < input.length()) { | ||
size_t start = input.find("{{", pos); | ||
if (start == std::string::npos) break; | ||
|
||
size_t end = input.find("}}", start); | ||
if (end == std::string::npos) break; | ||
|
||
std::string potential_key = input.substr(start, end - start + 2); | ||
auto key = extractKey(potential_key); | ||
|
||
if (key) { | ||
keys.push_back(*key); | ||
} | ||
|
||
pos = end + 2; | ||
} | ||
|
||
return keys; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#include <string> | ||
#include <optional> | ||
#include <vector> | ||
|
||
namespace facebook::react { | ||
|
||
class SLKeyExtractor { | ||
public: | ||
static std::optional<std::string> extractKey(const std::string& input); | ||
static std::vector<std::string> extractAllKeys(const std::string& input); | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#include "SLModuleJSI.h" | ||
|
||
namespace facebook::react { | ||
|
||
using namespace facebook; | ||
|
||
void SLModuleJSI::install(facebook::jsi::Runtime &runtime, std::shared_ptr<SLCommitHook> &commitHook) { | ||
auto registerContainerFamily = facebook::jsi::Function::createFromHostFunction( | ||
runtime, | ||
facebook::jsi::PropNameID::forAscii(runtime, "__NATIVE_registerContainerNode"), | ||
1, | ||
[&](facebook::jsi::Runtime &runtime, | ||
const facebook::jsi::Value &thisValue, | ||
const facebook::jsi::Value *arguments, | ||
size_t count) -> facebook::jsi::Value | ||
{ | ||
auto shadowNode = shadowNodeFromValue(runtime, arguments[0]); | ||
commitHook->registerContainerNode(shadowNode); | ||
|
||
return facebook::jsi::Value::undefined(); | ||
}); | ||
runtime.global().setProperty(runtime, "__NATIVE_registerContainerNode", std::move(registerContainerFamily)); | ||
|
||
auto unregisterContainerFamily = facebook::jsi::Function::createFromHostFunction( | ||
runtime, | ||
facebook::jsi::PropNameID::forAscii(runtime, "__NATIVE_unregisterContainerNode"), | ||
1, | ||
[&](facebook::jsi::Runtime &runtime, | ||
const facebook::jsi::Value &thisValue, | ||
const facebook::jsi::Value *arguments, | ||
size_t count) -> facebook::jsi::Value | ||
{ | ||
auto shadowNode = shadowNodeFromValue(runtime, arguments[0]); | ||
commitHook->unregisterContainerNode(shadowNode); | ||
|
||
return facebook::jsi::Value::undefined(); | ||
}); | ||
runtime.global().setProperty(runtime, "__NATIVE_unregisterContainerNode", std::move(unregisterContainerFamily)); | ||
|
||
auto registerElementFamily = facebook::jsi::Function::createFromHostFunction( | ||
runtime, | ||
facebook::jsi::PropNameID::forAscii(runtime, "__NATIVE_registerElementNode"), | ||
1, | ||
[&](facebook::jsi::Runtime &runtime, | ||
const facebook::jsi::Value &thisValue, | ||
const facebook::jsi::Value *arguments, | ||
size_t count) -> facebook::jsi::Value | ||
{ | ||
auto shadowNode = shadowNodeFromValue(runtime, arguments[0]); | ||
commitHook->registerElementNode(shadowNode); | ||
|
||
return facebook::jsi::Value::undefined(); | ||
}); | ||
runtime.global().setProperty(runtime, "__NATIVE_registerElementNode", std::move(registerElementFamily)); | ||
|
||
auto unregisterElementFamily = facebook::jsi::Function::createFromHostFunction( | ||
runtime, | ||
facebook::jsi::PropNameID::forAscii(runtime, "__NATIVE_unregisterElementNode"), | ||
1, | ||
[&](facebook::jsi::Runtime &runtime, | ||
const facebook::jsi::Value &thisValue, | ||
const facebook::jsi::Value *arguments, | ||
size_t count) -> facebook::jsi::Value | ||
{ | ||
auto shadowNode = shadowNodeFromValue(runtime, arguments[0]); | ||
commitHook->unregisterElementNode(shadowNode); | ||
|
||
return facebook::jsi::Value::undefined(); | ||
}); | ||
runtime.global().setProperty(runtime, "__NATIVE_unregisterElementNode", std::move(unregisterElementFamily)); | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#include "SLCommitHook.h" | ||
|
||
namespace facebook::react { | ||
|
||
class SLModuleJSI { | ||
public: | ||
static void install(facebook::jsi::Runtime &runtime, std::shared_ptr<SLCommitHook> &commitHook); | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#include "SLTemplate.h" | ||
|
||
namespace facebook::react { | ||
|
||
int nextFamilyTag = -2; | ||
|
||
auto adjustFamilyTag = [](int tag) { | ||
const int MIN_TAG_VALUE = -2e9; | ||
const int CLAMPED_TAG = -2; | ||
return tag < MIN_TAG_VALUE ? CLAMPED_TAG : tag - 2; | ||
}; | ||
|
||
ShadowNode::Shared SLTemplate::cloneShadowNodeTree(jsi::Runtime *runtime, nlohmann::json* elementData, const ShadowNode::Shared& shadowNode) | ||
{ | ||
auto const &componentDescriptor = shadowNode->getComponentDescriptor(); | ||
PropsParserContext propsParserContext{shadowNode->getSurfaceId(), *componentDescriptor.getContextContainer().get()}; | ||
|
||
nextFamilyTag = adjustFamilyTag(nextFamilyTag); | ||
|
||
InstanceHandle::Shared instanceHandle = std::make_shared<const InstanceHandle>( | ||
*runtime, | ||
shadowNode->getInstanceHandle(*runtime), | ||
shadowNode->getTag()); | ||
auto const fragment = ShadowNodeFamilyFragment{nextFamilyTag, shadowNode->getSurfaceId(), instanceHandle}; | ||
auto const family = componentDescriptor.createFamily(fragment); | ||
auto const props = componentDescriptor.cloneProps(propsParserContext, shadowNode->getProps(), {}); | ||
auto const state = componentDescriptor.createInitialState(props, family); | ||
auto const nextShadowNode = componentDescriptor.createShadowNode( | ||
ShadowNodeFragment{props, ShadowNodeFragment::childrenPlaceholder(), state}, family); | ||
|
||
RawTextShadowNode::ConcreteProps* interpolatedProps; | ||
if (shadowNode->getComponentName() == std::string("RawText")) { | ||
const Props::Shared& nextprops = nextShadowNode->getProps(); | ||
interpolatedProps = const_cast<RawTextShadowNode::ConcreteProps*>( | ||
static_cast<const RawTextShadowNode::ConcreteProps*>(nextprops.get()) | ||
); | ||
|
||
try { | ||
if (!SLKeyExtractor::extractKey(interpolatedProps->text).has_value()) { | ||
throw false; | ||
} | ||
|
||
auto elementDataPointer = nlohmann::json::json_pointer( | ||
"/" + SLKeyExtractor::extractKey(interpolatedProps->text).value() | ||
); | ||
|
||
if ((*elementData).contains(elementDataPointer) && (*elementData)[elementDataPointer].is_string()) { | ||
interpolatedProps->text = (*elementData)[elementDataPointer].get<std::string>(); | ||
} | ||
} catch (...) {} | ||
} | ||
|
||
for (const auto &childShadowNode : shadowNode->getChildren()) { | ||
auto const clonedChildShadowNode = cloneShadowNodeTree(runtime, elementData, childShadowNode); | ||
componentDescriptor.appendChild(nextShadowNode, clonedChildShadowNode); | ||
} | ||
|
||
return nextShadowNode; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#include <react/renderer/uimanager/UIManager.h> | ||
#include <react/renderer/components/text/RawTextShadowNode.h> | ||
#include "json.hpp" | ||
#include "SLKeyExtractor.h" | ||
|
||
namespace facebook::react { | ||
|
||
class SLTemplate { | ||
public: | ||
static ShadowNode::Shared cloneShadowNodeTree( | ||
jsi::Runtime *runtime, | ||
nlohmann::json* elementData, | ||
const ShadowNode::Shared& shadowNode); | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.