UNPKG

17.4 kBSource Map (JSON)View Raw
1{"version":3,"sources":["../../src/react/branching.js"],"names":["getValueWithBranchingLogicApplied","realm","parentX","parentY","value","needsKeys","searchAndFlagMatchingComponentTypes","x","y","xTypeParent","yTypeParent","ObjectValue","xType","yType","equals","ArrayValue","xElem","index","yElem","AbstractValue","kind","consequentVal","alternateVal","args","searchAndFlagMismatchingNonHostTypes","arrayDepth","StringValue","xProps","yProps","xChildren","yChildren","Value","xVal","yVal","isIntrinsicAndHasWidenedNumericProperty","applyBranchedLogicValue","NumberValue","BooleanValue","NullValue","UndefinedValue","newArray","elementValue","makeFinal","condValue","evaluateWithAbstractConditional","evaluateForEffects","wrapReactElementInBranchOrReturnValue","ExpectedBailOut","temporal","createTemporalFromBuildFunction","isPure","skipInvariant","AbstractObjectValue","values","ValuesDomain","temporalAlias"],"mappings":";;;;;;;;AAWA;;AACA;;AAYA;;AACA;;AACA;;AAQA;;AACA;;;;AAnCA;;;;;;;;;AASA;AAqCA;AACA;AACA;AACA;AACA;AACA;AAEO,SAASA,iCAAT,CACLC,KADK,EAELC,OAFK,EAGLC,OAHK,EAILC,KAJK,EAKE;AACP,MAAIC,YAAY,KAAhB,CADO,CAGP;;AACA,QAAMC,sCAAsC,CAACC,CAAD,EAAIC,CAAJ,EAAOC,WAAP,EAAoBC,WAApB,KAAoC;AAC9E;AACA;AAEA;AACA;AACA;AACA,QAAIH,aAAaI,kBAAb,IAA4B,2BAAeJ,CAAf,CAA5B,IAAiDC,aAAaG,kBAA9D,IAA6E,2BAAeH,CAAf,CAAjF,EAAoG;AAClG,UAAII,QAAQ,wBAAYX,KAAZ,EAAmBM,CAAnB,EAAsB,MAAtB,CAAZ;AACA,UAAIM,QAAQ,wBAAYZ,KAAZ,EAAmBO,CAAnB,EAAsB,MAAtB,CAAZ;;AAEA,UAAII,MAAME,MAAN,CAAaD,KAAb,KAAuB,CAACJ,YAAYK,MAAZ,CAAmBF,KAAnB,CAAxB,IAAqD,CAACF,YAAYI,MAAZ,CAAmBD,KAAnB,CAA1D,EAAqF;AACnFR,oBAAY,IAAZ;AACD;AACF,KAPD,MAOO,IAAIE,aAAaQ,iBAAjB,EAA6B;AAClC;AACA;AACA,oCAAkBd,KAAlB,EAAyBM,CAAzB,EAA4B,CAACS,KAAD,EAAQC,KAAR,KAAkB;AAC5C,YAAIC,QAAQV,CAAZ,CAD4C,CAE5C;AACA;AACA;;AACA,YAAIA,aAAaO,iBAAjB,EAA6B;AAC3BG,kBAAQ,wBAAYjB,KAAZ,EAAmBO,CAAnB,EAAsBS,QAAQ,EAA9B,CAAR;AACD;;AACDX,4CAAoCU,KAApC,EAA2CE,KAA3C,EAAkDT,WAAlD,EAA+DC,WAA/D;AACD,OATD;AAUD,KAbM,MAaA,IAAIF,aAAaO,iBAAjB,EAA6B;AAClC;AACA;AACA,oCAAkBd,KAAlB,EAAyBO,CAAzB,EAA4B,CAACU,KAAD,EAAQD,KAAR,KAAkB;AAC5C,YAAID,QAAQT,CAAZ,CAD4C,CAE5C;AACA;AACA;;AACA,YAAIA,aAAaQ,iBAAjB,EAA6B;AAC3BC,kBAAQ,wBAAYf,KAAZ,EAAmBM,CAAnB,EAAsBU,QAAQ,EAA9B,CAAR;AACD;;AACDX,4CAAoCU,KAApC,EAA2CE,KAA3C,EAAkDT,WAAlD,EAA+DC,WAA/D;AACD,OATD;AAUD,KAbM,MAaA,IAAIH,aAAaY,oBAAb,IAA8BZ,EAAEa,IAAF,KAAW,aAA7C,EAA4D;AACjE;AAEA,UAAI,GAAGC,aAAH,EAAkBC,YAAlB,IAAkCf,EAAEgB,IAAxC;AAEAjB,0CAAoCe,aAApC,EAAmDb,CAAnD,EAAsDC,WAAtD,EAAmEC,WAAnE;AACAJ,0CAAoCgB,YAApC,EAAkDd,CAAlD,EAAqDC,WAArD,EAAkEC,WAAlE;AACD,KAPM,MAOA,IAAIF,aAAaW,oBAAb,IAA8BX,EAAEY,IAAF,KAAW,aAA7C,EAA4D;AACjE;AAEA,UAAI,GAAGC,aAAH,EAAkBC,YAAlB,IAAkCd,EAAEe,IAAxC;AAEAjB,0CAAoCC,CAApC,EAAuCc,aAAvC,EAAsDZ,WAAtD,EAAmEC,WAAnE;AACAJ,0CAAoCC,CAApC,EAAuCe,YAAvC,EAAqDb,WAArD,EAAkEC,WAAlE;AACD;AACF,GAvDD,CAJO,CA6DP;;;AACA,QAAMc,uCAAuC,CAACjB,CAAD,EAAWC,CAAX,EAAqBiB,UAArB,KAAkD;AAC7F,QAAIlB,aAAaI,kBAAb,IAA4B,2BAAeJ,CAAf,CAA5B,IAAiDC,aAAaG,kBAA9D,IAA6E,2BAAeH,CAAf,CAAjF,EAAoG;AAClG,UAAII,QAAQ,wBAAYX,KAAZ,EAAmBM,CAAnB,EAAsB,MAAtB,CAAZ;AACA,UAAIM,QAAQ,wBAAYZ,KAAZ,EAAmBO,CAAnB,EAAsB,MAAtB,CAAZ;;AAEA,UAAII,iBAAiBc,kBAAjB,IAAgCb,iBAAiBa,kBAArD,EAAkE;AAChE,YAAIC,SAAS,wBAAY1B,KAAZ,EAAmBM,CAAnB,EAAsB,OAAtB,CAAb;AACA,YAAIqB,SAAS,wBAAY3B,KAAZ,EAAmBO,CAAnB,EAAsB,OAAtB,CAAb;;AACA,YAAImB,kBAAkBhB,kBAAlB,IAAiCiB,kBAAkBjB,kBAAvD,EAAoE;AAClE,cAAIkB,YAAY,wBAAY5B,KAAZ,EAAmB0B,MAAnB,EAA2B,UAA3B,CAAhB;AACA,cAAIG,YAAY,wBAAY7B,KAAZ,EAAmB2B,MAAnB,EAA2B,UAA3B,CAAhB;;AAEA,cAAIC,qBAAqBE,YAArB,IAA8BD,qBAAqBC,YAAvD,EAA8D;AAC5DP,iDAAqCK,SAArC,EAAgDC,SAAhD,EAA2DL,UAA3D;AACD;AACF;AACF,OAXD,MAWO,IAAI,CAACb,MAAME,MAAN,CAAaD,KAAb,CAAL,EAA0B;AAC/B,YAAI,GAAGmB,IAAH,EAASC,IAAT,IAAiB7B,MAAMmB,IAA3B;AACAjB,4CAAoC0B,IAApC,EAA0CC,IAA1C,EAAgDrB,KAAhD,EAAuDC,KAAvD;AACD;AACF,KAnBD,MAmBO,IACLE,kBAAWmB,uCAAX,CAAmD3B,CAAnD,KACAQ,kBAAWmB,uCAAX,CAAmD1B,CAAnD,CAFK,EAGL,CACA;AACA;AACD,KANM,MAMA,IAAID,aAAaQ,iBAAb,IAA2BU,eAAe,CAA9C,EAAiD;AACtD,oCAAkBxB,KAAlB,EAAyBM,CAAzB,EAA4B,CAACS,KAAD,EAAQC,KAAR,KAAkB;AAC5C,YAAIC,KAAJ;;AACA,YAAIV,aAAaO,iBAAjB,EAA6B;AAC3B;AACAG,kBAAQ,wBAAYjB,KAAZ,EAAmBO,CAAnB,EAAsBS,QAAQ,EAA9B,CAAR;AACD,SAHD,MAGO,IAAIA,UAAU,CAAd,EAAiB;AACtB;AACAC,kBAAQV,CAAR;AACD;;AAED,YAAIQ,iBAAiBe,YAAjB,IAA0Bb,iBAAiBa,YAA/C,EAAsD;AACpDP,+CAAqCR,KAArC,EAA4CE,KAA5C,EAAmDO,aAAa,CAAhE;AACD;AACF,OAbD;AAcD,KAfM,MAeA,IAAIjB,aAAaO,iBAAb,IAA2BU,eAAe,CAA9C,EAAiD;AACtD,oCAAkBxB,KAAlB,EAAyBO,CAAzB,EAA4B,CAACU,KAAD,EAAQD,KAAR,KAAkB;AAC5C,YAAID,KAAJ;;AACA,YAAIT,aAAaQ,iBAAjB,EAA6B;AAC3B;AACAC,kBAAQ,wBAAYf,KAAZ,EAAmBM,CAAnB,EAAsBU,QAAQ,EAA9B,CAAR;AACD,SAHD,MAGO,IAAIA,UAAU,CAAd,EAAiB;AACtB;AACAD,kBAAQT,CAAR;AACD;;AAED,YAAIS,iBAAiBe,YAAjB,IAA0Bb,iBAAiBa,YAA/C,EAAsD;AACpDP,+CAAqCR,KAArC,EAA4CE,KAA5C,EAAmDO,aAAa,CAAhE;AACD;AACF,OAbD;AAcD;AACF,GAzDD;;AA2DAD,uCAAqCtB,OAArC,EAA8CC,OAA9C,EAAuD,CAAvD;;AAEA,MAAIE,SAAJ,EAAe;AACb,WAAO8B,wBAAwBlC,KAAxB,EAA+BG,KAA/B,CAAP;AACD;;AACD,SAAOA,KAAP;AACD,C,CAED;AACA;;;AACA,SAAS+B,uBAAT,CAAiClC,KAAjC,EAA+CG,KAA/C,EAAoE;AAClE,MACEA,iBAAiBsB,kBAAjB,IACAtB,iBAAiBgC,kBADjB,IAEAhC,iBAAiBiC,mBAFjB,IAGAjC,iBAAiBkC,gBAHjB,IAIAlC,iBAAiBmC,qBALnB,EAME,CACA;AACD,GARD,MAQO,IAAInC,iBAAiBO,kBAAjB,IAAgC,2BAAeP,KAAf,CAApC,EAA2D;AAChE,WAAO,iCAAqBH,KAArB,EAA4BG,KAA5B,CAAP;AACD,GAFM,MAEA,IAAIA,iBAAiBW,iBAArB,EAAiC;AACtC,QAAIyB,WAAW,0BAAcvC,KAAd,EAAqBG,KAArB,EAA4BqC,gBAAgBN,wBAAwBlC,KAAxB,EAA+BwC,YAA/B,CAA5C,CAAf;AACAD,aAASE,SAAT;AACA,WAAOF,QAAP;AACD,GAJM,MAIA,IAAIpC,iBAAiBe,oBAAjB,IAAkCf,MAAMgB,IAAN,KAAe,aAArD,EAAoE;AACzE,QAAI,CAACuB,SAAD,EAAYtB,aAAZ,EAA2BC,YAA3B,IAA2ClB,MAAMmB,IAArD;AACA,4BAAUoB,qBAAqBxB,oBAA/B;AAEA,WAAOlB,MAAM2C,+BAAN,CACLD,SADK,EAEL,MAAM;AACJ,aAAO1C,MAAM4C,kBAAN,CACL,MAAMC,sCAAsC7C,KAAtC,EAA6CkC,wBAAwBlC,KAAxB,EAA+BoB,aAA/B,CAA7C,CADD,EAEL,IAFK,EAGL,oCAHK,CAAP;AAKD,KARI,EASL,MAAM;AACJ,aAAOpB,MAAM4C,kBAAN,CACL,MAAMC,sCAAsC7C,KAAtC,EAA6CkC,wBAAwBlC,KAAxB,EAA+BqB,YAA/B,CAA7C,CADD,EAEL,IAFK,EAGL,mCAHK,CAAP;AAKD,KAfI,CAAP;AAiBD,GArBM,MAqBA,IAAIlB,iBAAiBe,oBAAjB,KAAmCf,MAAMgB,IAAN,KAAe,IAAf,IAAuBhB,MAAMgB,IAAN,KAAe,IAAzE,CAAJ,EAAoF;AACzF,4BAAU,KAAV,EAAiB,+FAAjB;AACD,GAFM,MAEA;AACL,UAAM,IAAI2B,uBAAJ,CAAoB,sEAApB,CAAN;AACD;;AACD,SAAO3C,KAAP;AACD,C,CAED;AACA;AACA;AACA;AACA;AACA;AACA;;;AACO,SAAS0C,qCAAT,CAA+C7C,KAA/C,EAA6DG,KAA7D,EAAkF;AACvF,MAAIA,iBAAiBO,kBAAjB,IAAgC,2BAAeP,KAAf,CAApC,EAA2D;AACzD,QAAI4C,WAAW7B,qBAAc8B,+BAAd,CACbhD,KADa,EAEbU,kBAFa,EAGb,CAAC,8BAAkBV,KAAlB,EAAyBG,KAAzB,EAAgC,KAAhC,CAAD,CAHa,EAIb,0CAA0B,YAA1B,CAJa,EAKb;AAAE8C,cAAQ,IAAV;AAAgBC,qBAAe;AAA/B,KALa,CAAf;;AAOA,4BAAUH,oBAAoBI,0BAA9B;AACAJ,aAASK,MAAT,GAAkB,IAAIC,oBAAJ,CAAiBlD,KAAjB,CAAlB;AACAA,UAAMmD,aAAN,GAAsBP,QAAtB;AACD;;AACD,SAAO5C,KAAP;AACD","sourcesContent":["/**\n * Copyright (c) 2017-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n/* @flow strict-local */\n\nimport { Realm } from \"../realm.js\";\nimport {\n AbstractObjectValue,\n AbstractValue,\n ArrayValue,\n BooleanValue,\n NullValue,\n NumberValue,\n ObjectValue,\n StringValue,\n UndefinedValue,\n Value,\n} from \"../values/index.js\";\nimport invariant from \"../invariant.js\";\nimport { ValuesDomain } from \"../domains/index.js\";\nimport {\n cloneReactElement,\n isReactElement,\n addKeyToReactElement,\n forEachArrayValue,\n getProperty,\n mapArrayValue,\n} from \"./utils.js\";\nimport { ExpectedBailOut } from \"./errors.js\";\nimport { createOperationDescriptor } from \"../utils/generator.js\";\n\n// Branch status is used for when Prepack returns an abstract value from a render\n// that results in a conditional path occuring. This can be problematic for reconcilation\n// as the reconciler then needs to understand if this is the start of a new branch, or if\n// it's actually deep into an existing branch. If it's a new branch, we need to apply\n// keys to the root JSX element so that it keeps it identity (because we're folding trees).\n// Furthermore, we also need to bail-out of folding class components where they have lifecycle\n// events, as we can't merge lifecycles of mutliple trees when branched reliably\nexport type BranchStatusEnum = \"ROOT\" | \"NO_BRANCH\" | \"NEW_BRANCH\" | \"BRANCH\";\n\n// This function aims to determine if we need to add keys to the ReactElements\n// of the returned conditional abstract value branches. It does this by first\n// checking the parent branch nodes (these were use to render both respective branches)\n// for any cases where ReactElement types on host components mismatch.\n// Note: this implementation is not fully sound and is likely missing support\n// for all React reconcilation cases for handling of keys, see issue #1131\n\nexport function getValueWithBranchingLogicApplied(\n realm: Realm,\n parentX: Value,\n parentY: Value,\n value: AbstractValue\n): Value {\n let needsKeys = false;\n\n // we check the inlined value and see if the component types match\n const searchAndFlagMatchingComponentTypes = (x, y, xTypeParent, yTypeParent) => {\n // The returned value is the result of getting the \"render\" from a component.\n // We need to search the value returned to see if the nodes need keys adding to them.\n\n // 1. If we have <X? /> and <Y? />, then check if their\n // types are the same, if they are the same and the parent types\n // are not the same as then we need to add keys\n if (x instanceof ObjectValue && isReactElement(x) && y instanceof ObjectValue && isReactElement(y)) {\n let xType = getProperty(realm, x, \"type\");\n let yType = getProperty(realm, y, \"type\");\n\n if (xType.equals(yType) && !xTypeParent.equals(xType) && !yTypeParent.equals(yType)) {\n needsKeys = true;\n }\n } else if (x instanceof ArrayValue) {\n // If we have x: []\n // Go through the elements of array x\n forEachArrayValue(realm, x, (xElem, index) => {\n let yElem = y;\n // And if we also have y: [], with a given element from x\n // search element of y at the same index from x.\n // If y is not an array, then continue but use x: [] against y\n if (y instanceof ArrayValue) {\n yElem = getProperty(realm, y, index + \"\");\n }\n searchAndFlagMatchingComponentTypes(xElem, yElem, xTypeParent, yTypeParent);\n });\n } else if (y instanceof ArrayValue) {\n // If we have y: []\n // Go through the elements of array y\n forEachArrayValue(realm, y, (yElem, index) => {\n let xElem = x;\n // And if we also have x: [], with a given element from y\n // search element of x at the same index from y.\n // If x is not an array, then continue but use y: [] against x\n if (x instanceof ArrayValue) {\n xElem = getProperty(realm, x, index + \"\");\n }\n searchAndFlagMatchingComponentTypes(xElem, yElem, xTypeParent, yTypeParent);\n });\n } else if (x instanceof AbstractValue && x.kind === \"conditional\") {\n // if x is a conditional value like \"a ? b : c\",\n // then recusrively check b and c agaginst that y\n let [, consequentVal, alternateVal] = x.args;\n\n searchAndFlagMatchingComponentTypes(consequentVal, y, xTypeParent, yTypeParent);\n searchAndFlagMatchingComponentTypes(alternateVal, y, xTypeParent, yTypeParent);\n } else if (y instanceof AbstractValue && y.kind === \"conditional\") {\n // if y is a conditional value like \"a ? b : c\",\n // then recusrively check b and c agaginst that x\n let [, consequentVal, alternateVal] = y.args;\n\n searchAndFlagMatchingComponentTypes(x, consequentVal, xTypeParent, yTypeParent);\n searchAndFlagMatchingComponentTypes(x, alternateVal, xTypeParent, yTypeParent);\n }\n };\n\n // we first check our \"parent\" value, that was used to get the inlined value\n const searchAndFlagMismatchingNonHostTypes = (x: Value, y: Value, arrayDepth: number): void => {\n if (x instanceof ObjectValue && isReactElement(x) && y instanceof ObjectValue && isReactElement(y)) {\n let xType = getProperty(realm, x, \"type\");\n let yType = getProperty(realm, y, \"type\");\n\n if (xType instanceof StringValue && yType instanceof StringValue) {\n let xProps = getProperty(realm, x, \"props\");\n let yProps = getProperty(realm, y, \"props\");\n if (xProps instanceof ObjectValue && yProps instanceof ObjectValue) {\n let xChildren = getProperty(realm, xProps, \"children\");\n let yChildren = getProperty(realm, yProps, \"children\");\n\n if (xChildren instanceof Value && yChildren instanceof Value) {\n searchAndFlagMismatchingNonHostTypes(xChildren, yChildren, arrayDepth);\n }\n }\n } else if (!xType.equals(yType)) {\n let [, xVal, yVal] = value.args;\n searchAndFlagMatchingComponentTypes(xVal, yVal, xType, yType);\n }\n } else if (\n ArrayValue.isIntrinsicAndHasWidenedNumericProperty(x) ||\n ArrayValue.isIntrinsicAndHasWidenedNumericProperty(y)\n ) {\n // If either case is an unknown array, we do not know\n // the contents of the array, so we cannot add keys\n } else if (x instanceof ArrayValue && arrayDepth === 0) {\n forEachArrayValue(realm, x, (xElem, index) => {\n let yElem;\n if (y instanceof ArrayValue) {\n // handle the case of [x].equals([y])\n yElem = getProperty(realm, y, index + \"\");\n } else if (index === 0) {\n // handle the case of [x].equals(y)\n yElem = y;\n }\n\n if (xElem instanceof Value && yElem instanceof Value) {\n searchAndFlagMismatchingNonHostTypes(xElem, yElem, arrayDepth + 1);\n }\n });\n } else if (y instanceof ArrayValue && arrayDepth === 0) {\n forEachArrayValue(realm, y, (yElem, index) => {\n let xElem;\n if (x instanceof ArrayValue) {\n // handle the case of [y].equals([x]\n xElem = getProperty(realm, x, index + \"\");\n } else if (index === 0) {\n // handle the case of [y].equals(x)\n xElem = x;\n }\n\n if (xElem instanceof Value && yElem instanceof Value) {\n searchAndFlagMismatchingNonHostTypes(xElem, yElem, arrayDepth + 1);\n }\n });\n }\n };\n\n searchAndFlagMismatchingNonHostTypes(parentX, parentY, 0);\n\n if (needsKeys) {\n return applyBranchedLogicValue(realm, value);\n }\n return value;\n}\n\n// When we apply branching logic, it means to add keys to all ReactElement nodes\n// we encounter, thus returning new ReactElements with the keys on them\nfunction applyBranchedLogicValue(realm: Realm, value: Value): Value {\n if (\n value instanceof StringValue ||\n value instanceof NumberValue ||\n value instanceof BooleanValue ||\n value instanceof NullValue ||\n value instanceof UndefinedValue\n ) {\n // terminal values\n } else if (value instanceof ObjectValue && isReactElement(value)) {\n return addKeyToReactElement(realm, value);\n } else if (value instanceof ArrayValue) {\n let newArray = mapArrayValue(realm, value, elementValue => applyBranchedLogicValue(realm, elementValue));\n newArray.makeFinal();\n return newArray;\n } else if (value instanceof AbstractValue && value.kind === \"conditional\") {\n let [condValue, consequentVal, alternateVal] = value.args;\n invariant(condValue instanceof AbstractValue);\n\n return realm.evaluateWithAbstractConditional(\n condValue,\n () => {\n return realm.evaluateForEffects(\n () => wrapReactElementInBranchOrReturnValue(realm, applyBranchedLogicValue(realm, consequentVal)),\n null,\n \"applyBranchedLogicValue consequent\"\n );\n },\n () => {\n return realm.evaluateForEffects(\n () => wrapReactElementInBranchOrReturnValue(realm, applyBranchedLogicValue(realm, alternateVal)),\n null,\n \"applyBranchedLogicValue alternate\"\n );\n }\n );\n } else if (value instanceof AbstractValue && (value.kind === \"||\" || value.kind === \"&&\")) {\n invariant(false, \"applyBranchedLogicValue encounterted a logical expression (|| or &&), this should never occur\");\n } else {\n throw new ExpectedBailOut(\"Unsupported value encountered when applying branched logic to values\");\n }\n return value;\n}\n\n// when a ReactElement is resolved in a conditional branch we\n// can improve runtime performance by ensuring that the ReactElement\n// is only created lazily in that specific branch and referenced\n// from then on. To do this we create a temporal abstract value\n// and set its kind to \"branched ReactElement\" so we properly track\n// the original ReactElement. If we don't have a ReactElement,\n// return the original value\nexport function wrapReactElementInBranchOrReturnValue(realm: Realm, value: Value): Value {\n if (value instanceof ObjectValue && isReactElement(value)) {\n let temporal = AbstractValue.createTemporalFromBuildFunction(\n realm,\n ObjectValue,\n [cloneReactElement(realm, value, false)],\n createOperationDescriptor(\"SINGLE_ARG\"),\n { isPure: true, skipInvariant: true }\n );\n invariant(temporal instanceof AbstractObjectValue);\n temporal.values = new ValuesDomain(value);\n value.temporalAlias = temporal;\n }\n return value;\n}\n"],"file":"branching.js"}
\No newline at end of file