--!nonstrict -- ROBLOX upstream: https://github.com/facebook/react/blob/v17.0.2/packages/react/src/ReactLazy.js --[[ * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow *]] local Packages = script.Parent.Parent -- ROBLOX: use patched console from shared local Shared = require(Packages.Shared) local console = Shared.console local LuauPolyfill = require(Packages.LuauPolyfill) local inspect = LuauPolyfill.util.inspect local ReactTypes = require(Packages.Shared) type Wakeable = ReactTypes.Wakeable type Thenable = ReactTypes.Thenable local ReactSymbols = require(Packages.Shared).ReactSymbols local REACT_LAZY_TYPE = ReactSymbols.REACT_LAZY_TYPE local Uninitialized = -1 local Pending = 0 local Resolved = 1 local Rejected = 2 type UninitializedPayload = { -- ROBLOX deviaton: Luau doesn't support literals -- _status: -1, _status: number, _result: () -> Thenable<{ default: T, [string]: any }>, } type PendingPayload = { -- ROBLOX deviaton: Luau doesn't support literals -- _status: 0, _status: number, _result: Wakeable, } type ResolvedPayload = { -- ROBLOX deviaton: Luau doesn't support literals -- _status: 1, _status: number, _result: { default: T, [string]: any }, } type RejectedPayload = { -- ROBLOX deviaton: Luau doesn't support literals -- _status: 2, _status: number, _result: any, } type Payload = UninitializedPayload | PendingPayload | ResolvedPayload | RejectedPayload export type LazyComponent = { ["$$typeof"]: number, _payload: P, _init: (payload: P) -> T, -- ... } function lazyInitializer(payload: Payload): T if payload._status == Uninitialized then local ctor = payload._result local thenable = ctor() -- Transition to the next state. local pending: PendingPayload = payload :: any pending._status = Pending pending._result = thenable thenable:andThen(function(moduleObject) if payload._status == Pending then local defaultExport = moduleObject.default if _G.__DEV__ then if defaultExport == nil then console.error( "lazy: Expected the result of a dynamic import() call. " .. "Instead received: `%s`\n\nYour code should look like: \n " -- Break up imports to avoid accidentally parsing them as dependencies. -- ROBLOX deviation: Lua syntax in message .. "local MyComponent = lazy(function() return req" .. "quire(script.Parent.MyComponent) end)", inspect(moduleObject) ) end end -- Transition to the next state. local resolved: ResolvedPayload = payload :: any resolved._status = Resolved resolved._result = defaultExport end end, function(error_) if payload._status == Pending then -- Transition to the next state. local rejected: RejectedPayload = payload :: any rejected._status = Rejected rejected._result = error_ end end) end if payload._status == Resolved then return payload._result else error(payload._result) end end local exports = {} exports.lazy = function( ctor: () -> Thenable<{ default: T, [string]: any }> ): LazyComponent> local payload: Payload = { -- We use these fields to store the result. _status = -1, _result = ctor, } local lazyType: LazyComponent> = { ["$$typeof"] = REACT_LAZY_TYPE, _payload = payload, -- ROBLOX FIXME Luau: needs something even beyond normalization to avoid Property '_init' is not compatible. Type '(Payload) -> T?' could not be converted into '(Payload) -> T?'; different number of generic type parameters _init = lazyInitializer :: any, } if _G.__DEV__ then -- In production, this would just set it on the object. local defaultProps local propTypes -- $FlowFixMe setmetatable(lazyType, { __index = function(self, key) if key == "defaultProps" then return defaultProps end if key == "propTypes" then return propTypes end return end, __newindex = function(self, key, value) if key == "defaultProps" then console.error( "React.lazy(...): It is not supported to assign `defaultProps` to " .. "a lazy component import. Either specify them where the component " .. "is defined, or create a wrapping component around it." ) defaultProps = value -- Match production behavior more closely: -- $FlowFixMe setmetatable(self, { __index = function() end, __newindex = function() end, }) end if key == "propTypes" then console.error( "React.lazy(...): It is not supported to assign `propTypes` to " .. "a lazy component import. Either specify them where the component " .. "is defined, or create a wrapping component around it." ) propTypes = value -- Match production behavior more closely: -- $FlowFixMe setmetatable(self, { __index = function() end, __newindex = function() end, }) end end, }) end return lazyType end return exports