{-# LANGUAGE AllowAmbiguousTypes, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GeneralizedNewtypeDeriving, MultiParamTypeClasses, OverlappingInstances, PatternSynonyms, RankNTypes, RecordWildCards, ScopedTypeVariables, TypeOperators, TypeSynonymInstances #-} module Language.JavaScript.Interpret where import Control.Applicative ((<$>), (<|>), (<*>)) import Control.Lens (Lens', (.=), (?=), (%=)) import qualified Control.Lens as Lens (at, lens, use) import Control.Monad (void) import Control.Monad (forM, liftM2, when) import qualified Control.Monad.Trans.Except as Except (ExceptT, catchE, runExceptT, throwE) import qualified Control.Monad.Trans.State.Lazy as State (StateT(..), evalStateT) import Data.Default import Data.Int import Data.Fixed (mod') import Data.Map (Map) import qualified Data.Map as Map (empty, fromList, insert, lookup, member, toList) import Data.Maybe (fromJust, isJust) import Data.Word import Data.Bits ((.|.), (.&.), complement, shiftL, shiftR, xor) import Data.Foldable (foldlM) import Prelude (Bool(..), Double, Either(..), Integer, Maybe(..), String, Eq((/=), (==)), Floating(..), Fractional(..), Functor(..), Monad(..), Num((+), (-), (*), abs), Ord((>), (<), (>=), (<=)), Real, RealFloat, RealFrac, Show(..), ($), (.), (^), (++), (&&), (||), (!!), const, elem, error, flip, floor, foldl, fromInteger, fromIntegral, id, isInfinite, isNaN, isNegativeZero, length, maybe, mod, not, null, show, signum, snd, succ, undefined) import qualified Prelude import Safe (tailSafe) import Language.JavaScript.AST import Language.JavaScript.String import Language.JavaScript.SubType class Interpret f m t | f -> t where interpret :: f -> m t class Interpret1 f m p t | f -> p, f -> t where interpret1 :: f -> p -> m t instance (Functor m, Monad m) => Interpret Literal m Value where interpret (LiteralNull n) = do n' <- interpret n return $ inj n' interpret (LiteralBool b) = do b' <- interpret b return $ inj b' interpret (LiteralNum n) = do n' <- interpret n return $ inj n' interpret (LiteralString s) = do s' <- interpret s return $ inj s' interpret (LiteralRegExp r) = do r' <- interpret r return $ inj r' instance (Functor m, Monad m) => Interpret NullLit m Null where interpret NullLit = return Null instance (Functor m, Monad m) => Interpret BoolLit m Bool where interpret (BoolLit b) = return b instance (Functor m, Monad m) => Interpret StringLit m String where interpret (StringLit s) = return s instance (Functor m, Monad m) => Interpret NumLit m Number where interpret (NumLit n) = return $ Number n instance (Functor m, Monad m) => Interpret RegExpLit m Undefined where interpret (RegExpLit _) = return $ Undefined instance (Functor m, Monad m) => Interpret PrimExpr (JavaScriptT m) CallValue where interpret PrimExprThis = do v <- Lens.use $ contextStack . currentContext . thisBinding return $ inj v interpret (PrimExprIdent (Ident (IdentName s))) = do env <- Lens.use $ contextStack . currentContext . lexicalEnvironment let strict = False inj <$> getIdentifierReference (Just env) s strict interpret (PrimExprLiteral l) = do v <- interpret l return $ inj v interpret (PrimExprArray a) = do o <- interpret a return $ inj o interpret (PrimExprObject o) = do v <- interpret o return $ inj v interpret (PrimExprParens e) = do v <- interpret e return $ inj v instance (Functor m, Monad m) => Interpret ArrayLit (JavaScriptT m) Object where interpret (ArrayLitH me) = do a <- newArrayObject [] pad <- case me of Just e -> interpret e _ -> return $ Number 0 put a "length" (inj pad) False return a interpret (ArrayLit e) = interpret e interpret (ArrayLitT e mel) = do array <- interpret e pad <- case mel of Just el -> interpret el _ -> return $ Number 0 len <- get array "length" >>= toNumber newLen <- toUint32 (pad + len) put array "length" (inj $ Number $ fromIntegral newLen) False return array instance (Functor m, Monad m) => Interpret ObjectLit (JavaScriptT m) Object where interpret ObjectLitEmpty = do o <- newObjectObject Nothing return o interpret (ObjectLit pl) = interpret pl instance (Functor m, Monad m) => Interpret PropList (JavaScriptT m) Object where interpret (PropListAssign pa) = do obj <- newObjectObject Nothing PropertyIdentifier name desc <- interpret pa defineOwnProperty obj name desc False return obj interpret (PropListCons pl pa) = do obj <- interpret pl PropertyIdentifier name desc <- interpret pa mPrevious <- getOwnProperty obj name case mPrevious of JSJust previous -> return () JSNothing -> return () defineOwnProperty obj name desc False return obj instance (Functor m, Monad m) => Interpret PropAssign (JavaScriptT m) PropertyIdentifier where interpret (PropAssignField pn ae) = do propName <- interpret pn exprValue <- interpret ae propValue <- getValue exprValue let desc = def { propertyDescriptorValue = Just propValue, propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just True } return $ PropertyIdentifier propName desc interpret (PropAssignGet pn fb) = do propName <- interpret pn lex <- Lens.use $ contextStack . currentContext . lexicalEnvironment let strict = False closure <- newFunctionObject Nothing fb lex strict let desc = def { propertyDescriptorGet = Just closure, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just True } return $ PropertyIdentifier propName desc interpret (PropAssignSet pn (PropSetParamList i) fb) = do propName <- interpret pn lex <- Lens.use $ contextStack . currentContext . lexicalEnvironment let strict = False closure <- newFunctionObject (Just (FormalParamList i)) fb lex strict let desc = def { propertyDescriptorSet = Just closure, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just True } return $ PropertyIdentifier propName desc instance (Functor m, Monad m) => Interpret PropName (JavaScriptT m) String where interpret (PropNameId (IdentName s)) = return s interpret (PropNameStr (StringLit s)) = return s interpret (PropNameNum (NumLit n)) = do let nbr = Number n toString nbr instance (Functor m, Monad m) => Interpret Elision m Number where interpret (ElisionComma) = return $ Number 1 interpret (ElisionCons e ) = do Number n <- interpret e return $ Number (n+1) instance (Functor m, Monad m) => Interpret ElementList (JavaScriptT m) Object where interpret (ElementList me ae) = do array <- newArrayObject [] firstIndex <- case me of Just e -> interpret e _ -> return $ Number 0 initResult <- interpret ae initValue <- getValue initResult s <- toString firstIndex defineOwnProperty array s (def { propertyDescriptorValue = Just initValue, propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just True }) False return array interpret (ElementListCons el me ae) = do array <- interpret el pad <- case me of Just e -> interpret e _ -> return $ Number 0 initResult <- interpret ae initValue <- getValue initResult len <- get array "length" newLen <- pad `operatorPlus` len >>= toUint32 >>= toString . Number . fromIntegral let desc = def { propertyDescriptorValue = Just initValue, propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just True } defineOwnProperty array newLen desc False return array instance (Functor m, Monad m) => Interpret Stmt (JavaScriptT m) Completion where interpret (StmtBlock b) = interpret b interpret (StmtVar v) = interpret v interpret (StmtEmpty e) = interpret e interpret (StmtExpr e) = interpret e interpret (StmtIf i) = interpret i interpret (StmtIt i) = interpret i interpret (StmtCont c) = interpret c interpret (StmtBreak b) = interpret b interpret (StmtReturn r) = interpret r interpret (StmtWith w) = interpret w interpret (StmtLabelled l) = interpret l interpret (StmtSwitch s) = interpret s interpret (StmtThrow t) = interpret t interpret (StmtTry t) = interpret t interpret (StmtDbg d) = interpret d instance (Functor m, Monad m) => Interpret Block (JavaScriptT m) Completion where interpret (Block Nothing) = return $ Completion CompletionTypeNormal Nothing Nothing interpret (Block (Just sl)) = interpret sl instance (Functor m, Monad m) => Interpret StmtList (JavaScriptT m) Completion where interpret (StmtList stmt) = Except.catchE (interpret stmt) (\v -> return $ Completion CompletionTypeThrow (Just v) Nothing) interpret (StmtListCons sl stmt) = do slc <- interpret sl case slc of Completion CompletionTypeNormal slv _ -> Except.catchE (do s@(Completion sty sva sta) <- (interpret stmt :: JavaScriptT m Completion) if isJust sva then return $ Completion sty sva sta else return $ Completion sty slv sta) (\v -> return $ Completion CompletionTypeThrow (Just v) Nothing) _ -> return slc instance (Functor m, Monad m) => Interpret VarStmt (JavaScriptT m) Completion where interpret (VarStmt vdl) = do interpret vdl return $ Completion CompletionTypeNormal Nothing Nothing instance (Functor m, Monad m) => Interpret VarDeclList (JavaScriptT m) String where interpret (VarDeclList vd) = interpret vd interpret (VarDeclListCons vdl vd) = do interpret vdl interpret vd instance (Functor m, Monad m) => Interpret VarDeclListNoIn (JavaScriptT m) String where interpret (VarDeclListNoIn vd) = interpret vd interpret (VarDeclListNoInCons vdl vd) = do interpret vdl interpret vd instance (Functor m, Monad m) => Interpret VarDecl (JavaScriptT m) String where interpret (VarDecl (Ident (IdentName s)) Nothing) = return s interpret (VarDecl ident@(Ident (IdentName s)) (Just init)) = do lhs <- interpret ident rhs <- interpret init value <- getValue rhs putValue lhs value return s instance (Functor m, Monad m) => Interpret VarDeclNoIn (JavaScriptT m) String where interpret (VarDeclNoIn (Ident (IdentName s)) Nothing) = return s interpret (VarDeclNoIn ident@(Ident (IdentName s)) (Just init)) = do lhs <- interpret ident rhs <- interpret init value <- getValue rhs putValue lhs value return s instance (Functor m, Monad m) => Interpret Initialiser (JavaScriptT m) CallValue where interpret (Initialiser ae) = interpret ae instance (Functor m, Monad m) => Interpret InitialiserNoIn (JavaScriptT m) CallValue where interpret (InitialiserNoIn ae) = interpret ae instance (Functor m, Monad m) => Interpret EmptyStmt m Completion where interpret EmptyStmt = return $ Completion CompletionTypeNormal Nothing Nothing instance (Functor m, Monad m) => Interpret ExprStmt (JavaScriptT m) Completion where interpret (ExprStmt e) = do exprRef <- interpret e v <- getValue exprRef return $ Completion CompletionTypeNormal (Just v) Nothing instance (Functor m, Monad m) => Interpret IfStmt (JavaScriptT m) Completion where interpret (IfStmtIfElse e s1 s2) = do exprRef <- interpret e b <- getValue exprRef >>= return . toBoolean if b then interpret s1 else interpret s2 interpret (IfStmtIf e s) = do exprRef <- interpret e b <- getValue exprRef >>= return . toBoolean if b then interpret s else return $ Completion CompletionTypeNormal Nothing Nothing instance (Functor m, Monad m) => Interpret ItStmt (JavaScriptT m) Completion where interpret (ItStmtDoWhile stmt expr) = doWhile Nothing where doWhile :: Maybe Value -> JavaScriptT m Completion doWhile v = do s@(Completion sty sv sta) <- interpret stmt let v' = sv <|> v ils <- inCurrentLabelSet sta if sty /= CompletionTypeContinue || not ils then do if sty == CompletionTypeBreak && ils then return $ Completion CompletionTypeNormal v Nothing else if sty /= CompletionTypeNormal then return s else do exprRef <- interpret expr b <- getValue exprRef >>= return . toBoolean if b then doWhile v' else return $ Completion CompletionTypeNormal v' Nothing else do exprRef <- interpret expr b <- getValue exprRef >>= return . toBoolean if b then doWhile v' else return $ Completion CompletionTypeNormal v' Nothing interpret (ItStmtWhile expr stmt) = while Nothing where while :: Maybe Value -> JavaScriptM Completion while v = do exprRef <- interpret expr b <- getValue exprRef >>= return . toBoolean if not b then return $ Completion CompletionTypeNormal v Nothing else do s@(Completion sty sv sta) <- interpret stmt let v' = sv <|> v ils <- inCurrentLabelSet sta if sty /= CompletionTypeContinue || not ils then if sty == CompletionTypeBreak && ils then return $ Completion CompletionTypeNormal v' Nothing else if sty /= CompletionTypeNormal then return s else while v' else while v' interpret (ItStmtFor me1 me2 me3 s) = do case me1 of Just e1 -> do exprRef <- interpret e1 getValue exprRef return () _ -> return () for Nothing where for :: Maybe Value -> JavaScriptM Completion for v = do case me2 of Just e2 -> do testExprRef <- interpret e2 b <- getValue testExprRef >>= return . toBoolean if not b then return $ Completion CompletionTypeNormal v Nothing else runLoop v _ -> runLoop v runLoop v = do stmt@(Completion sty sv sta) <- interpret s let v' = sv <|> v ils <- inCurrentLabelSet sta if sty == CompletionTypeBreak && ils then return $ Completion CompletionTypeNormal v' Nothing else if (sty /= CompletionTypeContinue || not ils) && sty /= CompletionTypeNormal then return stmt else do case me3 of Just e3 -> do incExprRef <- interpret e3 getValue incExprRef return () Nothing -> return () for v' interpret (ItStmtForVar vdl me2 me3 s) = do interpret vdl for Nothing where for :: Maybe Value -> JavaScriptM Completion for v = do case me2 of Just e2 -> do testExprRef <- interpret e2 b <- getValue testExprRef >>= return . toBoolean if not b then return $ Completion CompletionTypeNormal v Nothing else runLoop v _ -> runLoop v runLoop v = do stmt@(Completion sty sv sta) <- interpret s let v' = sv <|> v ils <- inCurrentLabelSet sta if sty == CompletionTypeBreak && ils then return $ Completion CompletionTypeNormal v' Nothing else if (sty /= CompletionTypeContinue || not ils) && sty /= CompletionTypeNormal then return stmt else do case me3 of Just e3 -> do incExprRef <- interpret e3 getValue incExprRef return () Nothing -> return () for v' interpret (ItStmtForIn le e s) = do exprRef <- interpret e exprValue <- getValue exprRef case exprValue of ValueNull _ -> return $ Completion CompletionTypeNormal Nothing Nothing ValueUndefined _ -> return $ Completion CompletionTypeNormal Nothing Nothing _ -> do obj <- toObject exprValue ps <- Lens.use $ properties obj forIn (Map.toList ps) Nothing where forIn :: [(String, Property)] -> Maybe Value -> JavaScriptM Completion forIn [] v = return $ Completion CompletionTypeNormal v Nothing forIn ((p, pr):ps) v = do let enum = case pr of PropertyData (DataDescriptor {..}) -> dataDescriptorEnumerable PropertyAccessor (AccessorDescriptor {..}) -> accessorDescriptorEnumerable if enum then do lhsRef <- interpret le putValue lhsRef p stmt@(Completion sty sv sta) <- interpret s let v' = sv <|> v ils <- inCurrentLabelSet sta if sty == CompletionTypeBreak && ils then return $ Completion CompletionTypeNormal v Nothing else if (sty /= CompletionTypeContinue || not ils) && sty /= CompletionTypeNormal then return stmt else forIn ps v' else forIn ps v interpret (ItStmtForVarIn vd e s) = do varName <- interpret vd exprRef <- interpret e exprValue <- getValue exprRef case exprValue of ValueNull _ -> return $ Completion CompletionTypeNormal Nothing Nothing ValueUndefined _ -> return $ Completion CompletionTypeNormal Nothing Nothing _ -> do obj <- toObject exprValue ps <- Lens.use $ properties obj forIn (Map.toList ps) varName Nothing where forIn :: [(String, Property)] -> String -> Maybe Value -> JavaScriptM Completion forIn [] _ v = return $ Completion CompletionTypeNormal v Nothing forIn ((p, pr):ps) varName v = do let enum = case pr of PropertyData (DataDescriptor {..}) -> dataDescriptorEnumerable PropertyAccessor (AccessorDescriptor {..}) -> accessorDescriptorEnumerable if enum then do varRef <- interpret (Ident (IdentName varName)) putValue varRef p stmt@(Completion sty sv sta) <- interpret s let v' = sv <|> v ils <- inCurrentLabelSet sta if sty == CompletionTypeBreak && ils then return $ Completion CompletionTypeNormal v Nothing else if (sty /= CompletionTypeContinue || not ils) && sty /= CompletionTypeNormal then return stmt else forIn ps varName v' else forIn ps varName v instance (Functor m, Monad m) => Interpret ContStmt m Completion where interpret (ContStmt) = return $ Completion CompletionTypeContinue Nothing Nothing interpret (ContStmtLabelled i) = return $ Completion CompletionTypeContinue Nothing (Just i) instance (Functor m, Monad m) => Interpret BreakStmt m Completion where interpret (BreakStmt) = return $ Completion CompletionTypeBreak Nothing Nothing interpret (BreakStmtLabelled i) = return $ Completion CompletionTypeBreak Nothing (Just i) instance (Functor m, Monad m) => Interpret ReturnStmt (JavaScriptT m) Completion where interpret (ReturnStmt) = do return $ Completion CompletionTypeReturn (inj Undefined) Nothing interpret (ReturnStmtExpr e) = do exprRef <- interpret e v <- getValue exprRef return $ Completion CompletionTypeReturn (Just v) Nothing instance (Functor m, Monad m) => Interpret WithStmt (JavaScriptT m) Completion where interpret (WithStmt expr stmt) = do val <- interpret expr obj <- getValue val >>= toObject oldEnv <- Lens.use (contextStack . currentContext . lexicalEnvironment) newEnv <- newObjectObjectEnvironment obj (Just oldEnv) contextStack . currentContext . lexicalEnvironment .= newEnv c <- Except.catchE (interpret stmt :: JavaScriptT m Completion) (\v -> return $ Completion CompletionTypeThrow (Just v) Nothing) contextStack . currentContext . lexicalEnvironment .= oldEnv return c instance (Functor m, Monad m) => Interpret SwitchStmt (JavaScriptT m) Completion where interpret (SwitchStmt expr cb) = do exprRef <- interpret expr v <- getValue exprRef r@(Completion rty rv rta) <- interpret1 cb v case rty of CompletionTypeBreak -> if False then return $ Completion CompletionTypeNormal rv Nothing else return r _ -> return r instance (Functor m, Monad m) => Interpret1 CaseBlock (JavaScriptT m) Value Completion where interpret1 (CaseBlock mccs) = \input -> do let v = Nothing case mccs of Nothing -> return $ Completion CompletionTypeNormal v Nothing Just ccs -> do ecv <- search input ccs v case ecv of Left c -> return c Right (v', mrccs) -> do case mrccs of Nothing -> return $ Completion CompletionTypeNormal v' Nothing Just rccs -> falltrough rccs v' where search input (CaseClauses c@(CaseClause e msl)) v = do clauseSelector <- interpret c if input == clauseSelector then do case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl if cty /= CompletionTypeNormal then return $ Left r else return $ Right (cv, Nothing) Nothing -> return $ Right (v, Nothing) else return $ Left $ Completion CompletionTypeNormal v Nothing search input (CaseClausesCons ccs c@(CaseClause e msl)) v = do clauseSelector <- interpret c if input == clauseSelector then do case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl if cty /= CompletionTypeNormal then return $ Left r else return $ Right (cv, Just ccs) Nothing -> return $ Right (v, Just ccs) else search input ccs v falltrough (CaseClauses c@(CaseClause e msl)) v = do case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl let v' = cv <|> v if cty /= CompletionTypeNormal then return $ Completion cty v' cta else return $ Completion CompletionTypeNormal v' Nothing Nothing -> return $ Completion CompletionTypeNormal v Nothing falltrough (CaseClausesCons ccs c@(CaseClause e msl)) v = do case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl let v' = cv <|> v if cty /= CompletionTypeNormal then return $ Completion cty v' cta else falltrough ccs v' Nothing -> return $ Completion CompletionTypeNormal v Nothing interpret1 (CaseBlockDefault mfccs df@(DefaultClause msl) mrccs) = \input -> do let v = Nothing found = False ecvf <- case mfccs of Nothing -> return $ Right (v, found) Just fccs -> searchFirst input found fccs v case ecvf of Left c -> return c Right (v', found') -> do let foundInB = False ecvf' <- case (found, mrccs) of (False, _) -> return $ Right (v, foundInB, mrccs) (_, Nothing) -> return $ Right (v, foundInB, mrccs) (_, Just rccs) -> searchSecond input foundInB rccs v' case ecvf' of Left c -> return c Right (v'', foundInB', mrrccs) -> do case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl let v''' = cv <|> v'' if cty /= CompletionTypeNormal then return $ Completion cty v''' cta else do case mrrccs of Just rrccs -> falltrough rrccs v''' Nothing -> return $ Completion CompletionTypeNormal v''' Nothing where searchFirst input found cs@(CaseClauses c@(CaseClause e msl)) v = do if not found then do clauseSelector <- interpret c if input == clauseSelector then searchFirst input True cs v else return $ Right (v, found) else do case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl let v' = cv <|> v if cty /= CompletionTypeNormal then return $ Left $ Completion cty v' cta else return $ Right (v', found) Nothing -> return $ Right (v, found) searchFirst input found cccs@(CaseClausesCons ccs c) v = do if not found then do clauseSelector <- interpret c if input == clauseSelector then searchFirst input True cccs v else return $ Right (v, found) else do case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl let v' = cv <|> v if cty /= CompletionTypeNormal then return $ Left $ Completion cty v' cta else searchFirst input found ccs v' Nothing -> searchFirst input found ccs v searchSecond input foundInB cs@(CaseClauses c@(CaseClause e msl)) v = do clauseSelector <- interpret c if input == clauseSelector then do let foundInB' = True case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl let v' = cv <|> v if cty /= CompletionTypeNormal then return $ Left $ Completion cty v' cta else return $ Right (v', foundInB', Nothing) Nothing -> return $ Right (v, foundInB', Nothing) else return $ Right (v, foundInB, Nothing) searchSecond input foundInB (CaseClausesCons ccs c@(CaseClause e msl)) v = do clauseSelector <- interpret c if input == clauseSelector then do let foundInB' = True case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl let v' = cv <|> v if cty /= CompletionTypeNormal then return $ Left $ Completion cty v' cta else return $ Right (v', foundInB', Just ccs) Nothing -> return $ Right (v, foundInB', Just ccs) else searchSecond input foundInB ccs v falltrough cs@(CaseClauses c@(CaseClause e msl)) v = do case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl let v' = cv <|> v if cty /= CompletionTypeNormal then return $ Completion cty v' cta else return $ Completion CompletionTypeNormal v' Nothing Nothing -> return $ Completion CompletionTypeNormal v Nothing falltrough (CaseClausesCons ccs c@(CaseClause e msl)) v = do case msl of Just sl -> do r@(Completion cty cv cta) <- interpret sl let v' = cv <|> v if cty /= CompletionTypeNormal then return $ Completion cty v' cta else falltrough ccs v' Nothing -> falltrough ccs v instance (Functor m, Monad m) => Interpret CaseClause (JavaScriptT m) Value where interpret (CaseClause expr _) = do exprRef <- interpret expr getValue exprRef instance (Functor m, Monad m) => Interpret LabelledStmt (JavaScriptT m) Completion where interpret (LabelledStmt ident stmt) = do contextStack . currentContext . labels %= (ident:) c@(Completion cty cv cta) <- interpret stmt contextStack . currentContext . labels %= tailSafe if cty == CompletionTypeBreak && cta == Just ident then return $ Completion CompletionTypeNormal cv Nothing else return c instance (Functor m, Monad m) => Interpret ThrowStmt (JavaScriptT m) Completion where interpret (ThrowStmt expr) = do exprRef <- interpret expr v <- getValue exprRef return $ Completion CompletionTypeThrow (Just v) Nothing instance (Functor m, Monad m) => Interpret TryStmt (JavaScriptT m) Completion where interpret (TryStmtBC block catch) = do b@(Completion cty (Just cv) cta) <- interpret block if cty /= CompletionTypeThrow then return b else interpret1 catch cv interpret (TryStmtBF block finally) = do b@(Completion bcty bcv bcta) <- interpret block f@(Completion fcty fcv fcta) <- interpret finally if fcty == CompletionTypeNormal then return b else return f interpret (TryStmtBCF block catch finally) = do b@(Completion bcty (Just bcv) bcta) <- interpret block c <- if bcty == CompletionTypeThrow then interpret1 catch bcv else return b f@(Completion fcty fcv fcta) <- interpret finally if fcty == CompletionTypeNormal then return c else return f instance (Functor m, Monad m) => Interpret1 Catch (JavaScriptT m) Value Completion where interpret1 (Catch (Ident (IdentName ident)) block) = \c -> do oldEnv <- Lens.use (contextStack . currentContext . lexicalEnvironment) catchEnv <- newDeclarativeEnvironment (Just oldEnv) envRec <- Lens.use $ lexicalEnvironmentInternal catchEnv . environmentRecord createMutableBinding envRec ident Nothing setMutableBinding envRec ident c False contextStack . currentContext . lexicalEnvironment .= catchEnv b <- interpret block contextStack . currentContext . lexicalEnvironment .= oldEnv return b instance (Functor m, Monad m) => Interpret Finally (JavaScriptT m) Completion where interpret (Finally block) = interpret block instance (Functor m, Monad m) => Interpret DbgStmt (JavaScriptT m) Completion where interpret (DbgStmt) = return $ Completion CompletionTypeNormal Nothing Nothing instance (Functor m, Monad m) => Interpret FuncDecl (JavaScriptT m) Object where interpret (FuncDecl i mfpl fb) = do var <- Lens.use $ contextStack . currentContext . variableEnvironment let strict = False newFunctionObject mfpl fb var strict instance (Functor m, Monad m) => Interpret Program (JavaScriptT m) Completion where interpret program@(Program mses) = do case mses of Nothing -> return $ Completion CompletionTypeNormal Nothing Nothing Just ses -> do enterGlobalContext program result <- interpret ses popContext return result instance (Functor m, Monad m) => Interpret FuncExpr (JavaScriptT m) Object where interpret (FuncExpr Nothing mfpl fb) = do lex <- Lens.use $ contextStack . currentContext . lexicalEnvironment let strict = False newFunctionObject mfpl fb lex strict interpret (FuncExpr (Just (Ident (IdentName s))) mfpl fb) = do lex <- Lens.use $ contextStack . currentContext . lexicalEnvironment funcEnv <- newDeclarativeEnvironment (Just lex) envRec <- Lens.use $ lexicalEnvironmentInternal funcEnv . environmentRecord decEnvRec <- Lens.use $ environmentRecordInternal envRec . declarativeEnvironmentRecord createImmutableBindingDeclarative decEnvRec s let strict = False closure <- newFunctionObject mfpl fb funcEnv strict initializeImmutableBindingDeclarative decEnvRec s (inj closure) return closure instance (Functor m, Monad m) => Interpret FuncBody (JavaScriptT m) Completion where interpret (FuncBody Nothing) = return $ Completion CompletionTypeNormal (Just (inj Undefined)) Nothing interpret (FuncBody (Just ses)) = interpret ses instance (Functor m, Monad m) => Interpret SourceElements (JavaScriptT m) Completion where interpret (SourceElementsCons ses se) = do headResult@(Completion hcty hcv hcta) <- interpret ses if hcty /= CompletionTypeNormal then return headResult else do tailResult@(Completion tcty tcv tcta) <- interpret se let v = tcv <|> hcv return $ Completion tcty v tcta interpret (SourceElements se) = interpret se instance (Functor m, Monad m) => Interpret SourceElement (JavaScriptT m) Completion where interpret (SourceElementStmt s) = interpret s interpret (SourceElementFuncDecl fd) = return $ Completion CompletionTypeNormal Nothing Nothing instance (Functor m, Monad m) => Interpret UExpr (JavaScriptT m) CallValue where interpret (UExprPostFix pfe) = interpret pfe interpret (UExprDelete ue) = do (rv :: CallValue) <- interpret ue case rv of Left ref -> do case getBase ref of BaseUndefined _ -> do if isStrictReference ref then newSyntaxErrorObject Nothing >>= jsThrow else return $ inj True BaseProperty propertyBase -> do obj <- toObject $ inj propertyBase inj <$> delete obj (getReferencedName ref) (isStrictReference ref) BaseEnvironmentRecord environmentRecordBase -> do if isStrictReference ref then newSyntaxErrorObject Nothing >>= jsThrow else do inj <$> deleteBinding environmentRecordBase (getReferencedName ref) interpret (UExprVoid ue) = do expr <- interpret ue getValue expr return $ inj Undefined interpret (UExprTypeOf ue) = do vr <- interpret ue case vr of Left ref -> do if isUnresolvableReference ref then return $ inj "undefined" else do val <- getValue ref return . inj . show $ typeOf val Right val -> do return . inj . show $ typeOf val interpret (UExprDoublePlus ue) = do (expr :: CallValue) <- interpret ue case prj expr of Just ref -> do if isStrictReference ref then do case prj (getBase ref) of Just (er :: EnvironmentRecord) -> do let name = getReferencedName ref if name == "eval" || name == "arguments" then newSyntaxErrorObject Nothing >>= jsThrow else return () Nothing -> return () else return () Nothing -> return () v <- getValue expr oldValue <- toNumber v let newValue = oldValue + (Number 1) putValue expr newValue return $ inj newValue interpret (UExprDoubleMinus ue) = do expr <- interpret ue case prj expr of Just ref -> do if isStrictReference ref then do case prj (getBase ref) of Just (er :: EnvironmentRecord) -> do let name = getReferencedName ref if name == "eval" || name == "arguments" then newSyntaxErrorObject Nothing >>= jsThrow else return () Nothing -> return () else return () Nothing -> return () v <- getValue expr oldValue <- toNumber v let newValue = oldValue - (Number 1) putValue expr newValue return $ inj newValue interpret (UExprUnaryPlus ue) = do expr <- interpret ue v <- getValue expr inj <$> toNumber v interpret (UExprUnaryMinus ue) = do expr <- interpret ue v <- getValue expr oldValue <- toNumber v return $ inj (-oldValue) interpret (UExprBitNot ue) = do expr <- interpret ue v <- getValue expr oldValue <- toInt32 v return $ inj $ Number (fromIntegral $ complement oldValue) interpret (UExprNot ue) = do expr <- interpret ue v <- getValue expr let oldValue = toBoolean v return $ inj $ not oldValue instance (Functor m, Monad m) => Interpret MemberExpr (JavaScriptT m) CallValue where interpret (MemberExprPrim pe) = do v <- interpret pe return $ inj v interpret (MemberExprFunc fe) = do (o :: Object) <- interpret fe return $ inj o interpret (MemberExprArray me expr) = do baseReference <- interpret me baseValue <- getValue baseReference propertyNameReference <- interpret expr propertyNameValue <- getValue propertyNameReference baseValueCoercible <- toObjectCoercible baseValue propertyNameString <- toString propertyNameValue let strict = False return $ inj $ Reference (inj baseValueCoercible) propertyNameString strict interpret (MemberExprDot me (IdentName s)) = do baseReference <- interpret me baseValue <- getValue baseReference baseValueCoercible <- toObjectCoercible baseValue let strict = False return $ inj $ Reference (inj baseValueCoercible) s strict interpret (MemberExprNew me args) = do ref <- interpret me constructor <- getValue ref argList <- interpret args case constructor of ValueObject o -> do inj <$> construct o argList _ -> newTypeErrorObject Nothing >>= jsThrow instance (Functor m, Monad m) => Interpret NewExpr (JavaScriptT m) CallValue where interpret (NewExprMember me) = interpret me interpret (NewExprNew ne) = do ref <- interpret ne constructor <- getValue ref case constructor of ValueObject o -> do inj <$> construct o (List []) _ -> newTypeErrorObject Nothing >>= jsThrow instance (Functor m, Monad m) => Interpret CallExpr (JavaScriptT m) CallValue where interpret (CallExprMember me args) = do rv <- interpret me func <- getValue rv argList <- interpret args case func of ValueObject o -> do thisValue <- case rv of Left ref -> do case toPropertyReference ref of Right propertyBase -> return $ inj propertyBase Left (Left er) -> do implicitThisValue er _ -> return $ inj Undefined call o thisValue argList _ -> newTypeErrorObject Nothing >>= jsThrow interpret (CallExprCall ce args) = do rv <- interpret ce func <- getValue rv argList <- interpret args case func of ValueObject o -> do thisValue <- case rv of Left ref -> do case toPropertyReference ref of Right propertyBase -> return $ inj propertyBase Left (Left er) -> do implicitThisValue er _ -> return $ inj Undefined call o thisValue argList _ -> newTypeErrorObject Nothing >>= jsThrow interpret (CallExprArray ce expr) = do baseReference <- interpret ce baseValue <- getValue baseReference propertyNameReference <- interpret expr propertyNameValue <- getValue propertyNameReference baseValueCoercible <- toObjectCoercible baseValue propertyNameString <- toString propertyNameValue let strict = False return $ inj $ Reference (inj baseValueCoercible) propertyNameString strict interpret (CallExprDot ce (IdentName s)) = do baseReference <- interpret ce baseValue <- getValue baseReference baseValueCoercible <- toObjectCoercible baseValue let strict = False return $ inj $ Reference (inj baseValueCoercible) s strict instance (Functor m, Monad m) => Interpret Arguments (JavaScriptT m) (List Value) where interpret (ArgumentsEmpty) = return (List []) interpret (Arguments al) = interpret al instance (Functor m, Monad m) => Interpret ArgumentList (JavaScriptT m) (List Value) where interpret (ArgumentList ae) = do ref <- interpret ae arg <- getValue ref return $ List [arg] interpret (ArgumentListCons al ae) = do List precedingArgs <- interpret al ref <- interpret ae arg <- getValue ref return $ List (precedingArgs ++ [arg]) instance (Functor m, Monad m) => Interpret LeftExpr (JavaScriptT m) CallValue where interpret (LeftExprNewExpr ne) = do v <- interpret ne return $ inj v interpret (LeftExprCallExpr ce) = interpret ce instance (Functor m, Monad m) => Interpret PostFixExpr (JavaScriptT m) CallValue where interpret (PostFixExprLeftExpr le) = interpret le interpret (PostFixExprPostInc le) = do lhs <- interpret le case lhs of CallValueReference ref -> when (isStrictReference ref) $ do case getBase ref of BaseEnvironmentRecord _ -> do let name = getReferencedName ref when (name == "eval" || name == "arguments") $ newSyntaxErrorObject Nothing >>= jsThrow _ -> return () _ -> return () oldValue <- getValue lhs >>= toNumber let newValue = oldValue + (Number 1) putValue lhs newValue return (inj oldValue) interpret (PostFixExprPostDec le) = do lhs <- interpret le case lhs of CallValueReference ref -> when (isStrictReference ref) $ do case getBase ref of BaseEnvironmentRecord _ -> do let name = getReferencedName ref when (name == "eval" || name == "arguments") $ newSyntaxErrorObject Nothing >>= jsThrow _ -> return () _ -> return () oldValue <- getValue lhs >>= toNumber let newValue = oldValue - (Number 1) putValue lhs newValue return (inj oldValue) instance (Functor m, Monad m) => Interpret MultExpr (JavaScriptT m) CallValue where interpret (MultExpr ue) = interpret ue interpret (MultExprMult me ue) = do left <- interpret me right <- interpret ue inj <$> left `operatorMult` right interpret (MultExprDiv me ue) = do left <- interpret me right <- interpret ue inj <$> left `operatorDiv` right interpret (MultExprMod me ue) = do left <- interpret me right <- interpret ue inj <$> left `operatorMod` right instance (Functor m, Monad m) => Interpret AddExpr (JavaScriptT m) CallValue where interpret (AddExpr me) = interpret me interpret (AddExprAdd ae me) = do lref <- interpret ae rref <- interpret me inj <$> lref `operatorPlus` rref interpret (AddExprSub ae me) = do lref <- interpret ae rref <- interpret me inj <$> lref `operatorMinus` rref instance (Functor m, Monad m) => Interpret ShiftExpr (JavaScriptT m) CallValue where interpret (ShiftExpr ae) = interpret ae interpret (ShiftExprLeft se ae) = do lref <- interpret se rref <- interpret ae inj <$> lref `operatorLeftShift` rref interpret (ShiftExprRight se ae) = do lref <- interpret se rref <- interpret ae inj <$> lref `operatorSignedRightShift` rref interpret (ShiftExprRightZero se ae) = do lref <- interpret se rref <- interpret ae inj <$> lref `operatorUnsignedRightShift` rref instance (Functor m, Monad m) => Interpret RelExpr (JavaScriptT m) CallValue where interpret (RelExpr se) = interpret se interpret (RelExprLess re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref mr <- compareLess lval rval True case mr of JSNothing -> return $ inj False JSJust r -> return $ inj r interpret (RelExprGreater re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref mr <- compareLess rval lval False case mr of JSNothing -> return $ inj False JSJust r -> return $ inj r interpret (RelExprLessEq re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref mr <- compareLess rval lval False case mr of JSNothing -> return $ inj False JSJust _ -> return $ inj True interpret (RelExprGreaterEq re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref mr <- compareLess lval rval True case mr of JSNothing -> return $ inj False JSJust True -> return $ inj False JSJust False -> return $ inj True interpret (RelExprInstanceOf re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref case rval of ValueObject o -> do inj <$> hasInstance o lval _ -> newTypeErrorObject Nothing >>= jsThrow interpret (RelExprIn re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref case prj rval of Nothing -> newTypeErrorObject Nothing >>= jsThrow Just obj -> do s <- toString lval inj <$> hasProperty obj s instance (Functor m, Monad m) => Interpret RelExprNoIn (JavaScriptT m) CallValue where interpret (RelExprNoIn se) = interpret se interpret (RelExprNoInLess re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref mr <- compareLess lval rval True case mr of JSNothing -> return $ inj False JSJust r -> return $ inj r interpret (RelExprNoInGreater re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref mr <- compareLess rval lval False case mr of JSNothing -> return $ inj False JSJust r -> return $ inj r interpret (RelExprNoInLessEq re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref mr <- compareLess rval lval False case mr of JSNothing -> return $ inj False JSJust _ -> return $ inj True interpret (RelExprNoInGreaterEq re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref mr <- compareLess lval rval True case mr of JSNothing -> return $ inj False JSJust True -> return $ inj False JSJust False -> return $ inj True interpret (RelExprNoInInstanceOf re se) = do lref <- interpret re lval <- getValue lref rref <- interpret se rval <- getValue rref case rval of ValueObject obj -> inj <$> hasInstance obj lval _ -> newTypeErrorObject Nothing >>= jsThrow instance (Functor m, Monad m) => Interpret EqExpr (JavaScriptT m) CallValue where interpret (EqExpr re) = interpret re interpret (EqExprEq eq re) = do lref <- interpret eq lval <- getValue lref rref <- interpret re rval <- getValue rref inj <$> compare rval lval interpret (EqExprNotEq eq re) = do lref <- interpret eq lval <- getValue lref rref <- interpret re rval <- getValue rref r <- compare rval lval return $ inj $ not r interpret (EqExprStrictEq eq re) = do lref <- interpret eq lval <- getValue lref rref <- interpret re rval <- getValue rref return $ inj $ compareStrict rval lval interpret (EqExprStrictNotEq eq re) = do lref <- interpret eq lval <- getValue lref rref <- interpret re rval <- getValue rref return $ inj $ not $ compareStrict rval lval instance (Functor m, Monad m) => Interpret EqExprNoIn (JavaScriptT m) CallValue where interpret (EqExprNoIn re) = interpret re interpret (EqExprNoInEq eq re) = do lref <- interpret eq lval <- getValue lref rref <- interpret re rval <- getValue rref inj <$> compare rval lval interpret (EqExprNoInNotEq eq re) = do lref <- interpret eq lval <- getValue lref rref <- interpret re rval <- getValue rref r <- compare rval lval return $ inj $ not r interpret (EqExprNoInStrictEq eq re) = do lref <- interpret eq lval <- getValue lref rref <- interpret re rval <- getValue rref return $ inj $ compareStrict rval lval interpret (EqExprNoInStrictNotEq eq re) = do lref <- interpret eq lval <- getValue lref rref <- interpret re rval <- getValue rref return $ inj $ not $ compareStrict rval lval instance (Functor m, Monad m) => Interpret BitAndExpr (JavaScriptT m) CallValue where interpret (BitAndExpr eq) = interpret eq interpret (BitAndExprAnd bae eq) = do lref <- interpret bae rref <- interpret eq inj <$> lref `operatorBitwiseAnd` rref instance (Functor m, Monad m) => Interpret BitAndExprNoIn (JavaScriptT m) CallValue where interpret (BitAndExprNoIn eq) = interpret eq interpret (BitAndExprNoInAnd bae eq) = do lref <- interpret bae rref <- interpret eq inj <$> lref `operatorBitwiseAnd` rref instance (Functor m, Monad m) => Interpret BitXorExpr (JavaScriptT m) CallValue where interpret (BitXorExpr eq) = interpret eq interpret (BitXorExprXor bae eq) = do lref <- interpret bae rref <- interpret eq inj <$> lref `operatorBitwiseXor` rref instance (Functor m, Monad m) => Interpret BitXorExprNoIn (JavaScriptT m) CallValue where interpret (BitXorExprNoIn eq) = interpret eq interpret (BitXorExprNoInXor bae eq) = do lref <- interpret bae rref <- interpret eq inj <$> lref `operatorBitwiseXor` rref instance (Functor m, Monad m) => Interpret BitOrExpr (JavaScriptT m) CallValue where interpret (BitOrExpr eq) = interpret eq interpret (BitOrExprOr bae eq) = do lref <- interpret bae rref <- interpret eq inj <$> lref `operatorBitwiseOr` rref instance (Functor m, Monad m) => Interpret BitOrExprNoIn (JavaScriptT m) CallValue where interpret (BitOrExprNoIn eq) = interpret eq interpret (BitOrExprNoInOr bae eq) = do lref <- interpret bae rref <- interpret eq inj <$> lref `operatorBitwiseOr` rref instance (Functor m, Monad m) => Interpret LogicalAndExpr (JavaScriptT m) CallValue where interpret (LogicalAndExpr boe) = interpret boe interpret (LogicalAndExprAnd lae boe) = do lref <- interpret lae lval <- getValue lref if not $ toBoolean lval then return $ inj lval else do rref <- interpret boe inj <$> getValue rref instance (Functor m, Monad m) => Interpret LogicalAndExprNoIn (JavaScriptT m) CallValue where interpret (LogicalAndExprNoIn boe) = do n <- interpret boe return $ inj n interpret (LogicalAndExprNoInAnd lae boe) = do lref <- interpret lae lval <- getValue lref if not $ toBoolean lval then return $ inj lval else do rref <- interpret boe inj <$> getValue rref instance (Functor m, Monad m) => Interpret LogicalOrExpr (JavaScriptT m) CallValue where interpret (LogicalOrExpr boe) = interpret boe interpret (LogicalOrExprOr lae boe) = do lref <- interpret lae lval <- getValue lref if not $ toBoolean lval then return $ inj lval else do rref <- interpret boe inj <$> getValue rref instance (Functor m, Monad m) => Interpret LogicalOrExprNoIn (JavaScriptT m) CallValue where interpret (LogicalOrExprNoIn boe) = interpret boe interpret (LogicalOrExprNoInOr lae boe) = do lref <- interpret lae lval <- getValue lref if toBoolean lval then return $ inj lval else do rref <- interpret boe inj <$> getValue rref instance (Functor m, Monad m) => Interpret CondExpr (JavaScriptT m) CallValue where interpret (CondExpr loe) = interpret loe interpret (CondExprIf loe ae1 ae2) = do lref <- interpret loe lval <- getValue lref if toBoolean lval then do trueRef <- interpret ae1 inj <$> getValue trueRef else do falseRef <- interpret ae2 inj <$> getValue falseRef instance (Functor m, Monad m) => Interpret CondExprNoIn (JavaScriptT m) CallValue where interpret (CondExprNoIn loe) = interpret loe interpret (CondExprNoInIf loe ae1 ae2) = do lref <- interpret loe lval <- getValue lref if toBoolean lval then do trueRef <- interpret ae1 inj <$> getValue trueRef else do falseRef <- interpret ae2 inj <$> getValue falseRef instance (Functor m, Monad m) => Interpret AssignExpr (JavaScriptT m) CallValue where interpret (AssignExprCondExpr ce) = interpret ce interpret (AssignExprAssign le AssignOpNormal ae) = do lref <- interpret le rref <- interpret ae rval <- getValue rref case lref of CallValueReference ref -> do when (isStrictReference ref && typeOf (getBase ref) == TypeEnvironmentRecord && (getReferencedName ref == "eval" || getReferencedName ref == "arguments")) $ do newSyntaxErrorObject Nothing >>= jsThrow _ -> return () putValue lref rval return $ inj rval interpret (AssignExprAssign le aop ae) = do lref <- interpret le lval <- getValue lref rref <- interpret ae rval <- getValue rref r <- case aop of AssignOpMult -> inj <$> lval `operatorMult` rval AssignOpDiv -> inj <$> lval `operatorDiv` rval AssignOpMod -> inj <$> lval `operatorMod` rval AssignOpPlus -> lval `operatorPlus` rval AssignOpMinus -> inj <$> lval `operatorMinus` rval AssignOpShiftLeft -> inj <$> lval `operatorLeftShift` rval AssignOpShiftRight -> inj <$> lval `operatorSignedRightShift` rval AssignOpShiftRightZero -> inj <$> lval `operatorUnsignedRightShift` rval AssignOpBitAnd -> inj <$> lval `operatorBitwiseAnd` rval AssignOpBitXor -> inj <$> lval `operatorBitwiseXor` rval AssignOpBitOr -> inj <$> lval `operatorBitwiseOr` rval case lref of CallValueReference ref -> do when (isStrictReference ref && typeOf (getBase ref) == TypeEnvironmentRecord && (getReferencedName ref == "eval" || getReferencedName ref == "arguments")) $ do newSyntaxErrorObject Nothing >>= jsThrow _ -> return () putValue lref r return $ inj r instance (Functor m, Monad m) => Interpret AssignExprNoIn (JavaScriptT m) CallValue where interpret (AssignExprNoInCondExpr ce) = interpret ce interpret (AssignExprNoInAssign le AssignOpNormal ae) = do lref <- interpret le rref <- interpret ae rval <- getValue rref case prj lref of Just ref -> do when (isStrictReference ref && typeOf (getBase ref) == TypeEnvironmentRecord && (getReferencedName ref == "eval" || getReferencedName ref == "arguments")) $ do newSyntaxErrorObject Nothing >>= jsThrow Nothing -> return () putValue lref rval return $ inj rval interpret (AssignExprNoInAssign le aop ae) = do lref <- interpret le lval <- getValue lref rref <- interpret ae rval <- getValue rref r <- case aop of AssignOpMult -> inj <$> lval `operatorMult` rval AssignOpDiv -> inj <$> lval `operatorDiv` rval AssignOpMod -> inj <$> lval `operatorMod` rval AssignOpPlus -> lval `operatorPlus` rval AssignOpMinus -> inj <$> lval `operatorMinus` rval AssignOpShiftLeft -> inj <$> lval `operatorLeftShift` rval AssignOpShiftRight -> inj <$> lval `operatorSignedRightShift` rval AssignOpShiftRightZero -> inj <$> lval `operatorUnsignedRightShift` rval AssignOpBitAnd -> inj <$> lval `operatorBitwiseAnd` rval AssignOpBitXor -> inj <$> lval `operatorBitwiseXor` rval AssignOpBitOr -> inj <$> lval `operatorBitwiseOr` rval case prj lref of Just ref -> do when (isStrictReference ref && typeOf (getBase ref) == TypeEnvironmentRecord && (getReferencedName ref == "eval" || getReferencedName ref == "arguments")) $ do newSyntaxErrorObject Nothing >>= jsThrow Nothing -> return () putValue lref r return $ inj r instance (Functor m, Monad m) => Interpret Expr (JavaScriptT m) CallValue where interpret (Expr ae) = interpret ae interpret (ExprCons e ae) = do lref <- interpret e getValue lref rref <- interpret ae inj <$> getValue rref instance (Functor m, Monad m) => Interpret ExprNoIn (JavaScriptT m) CallValue where interpret (ExprNoIn ae) = interpret ae interpret (ExprNoInCons e ae) = do lref <- interpret e getValue lref rref <- interpret ae inj <$> getValue rref instance (Functor m, Monad m) => Interpret Ident (JavaScriptT m) Reference where interpret (Ident (IdentName s)) = do env <- Lens.use $ contextStack . currentContext . lexicalEnvironment let strict = False getIdentifierReference (Just env) s strict declarationBindingInstantiation :: (Functor m, Monad m) => Code -> JavaScriptT m () declarationBindingInstantiation c = do let strict = False configurableBindings = case c of CodeEval {} -> True _ -> False case c of CodeFunction func args -> do (FuncBody mses) <- code func (lex, env) <- step1 dec <- Lens.use $ environmentRecordInternal env . declarativeEnvironmentRecord names <- step2 strict dec func args case mses of Just ses -> do step3 strict configurableBindings env ses argumentsAlreadyDeclared <- step4 env when (not argumentsAlreadyDeclared) $ do step5 strict lex dec func names args step6 strict configurableBindings env ses return () Nothing -> do argumentsAlreadyDeclared <- step4 env when (not argumentsAlreadyDeclared) $ do step5 strict lex dec func names args return () CodeGlobal (Program mses) -> do (lex, env) <- step1 case mses of Just ses -> do step3 strict configurableBindings env ses step4 env step6 strict configurableBindings env ses return () Nothing -> do step4 env return () where step1 :: (Functor m, Monad m) => JavaScriptT m (LexicalEnvironment, EnvironmentRecord) step1 = do var <- Lens.use $ contextStack . currentContext . variableEnvironment env <- Lens.use $ lexicalEnvironmentInternal var . environmentRecord return (var, env) step2 :: (Functor m, Monad m) => Bool -> DeclarativeEnvironmentRecord -> Object -> List Value -> JavaScriptT m (List String) step2 strict env func args@(List as) = do names@(List ns) <- formalParameters func let argCount = length as n = 0 (flip . flip foldlM) n ns $ \n argName -> do let n' = n+1 v = if n' > argCount then inj Undefined else as !! (n' - 1) argAlreadyDeclared <- hasBindingDeclarative env argName when (not argAlreadyDeclared) $ do createMutableBindingDeclarative env argName Nothing setMutableBindingDeclarative env argName v strict return n' return names step3 :: (Functor m, Monad m) => Bool -> Bool -> EnvironmentRecord -> SourceElements -> JavaScriptT m () step3 strict configurableBindings env ses = do forM (extractFuncDecls ses) $ \f@(FuncDecl (Ident (IdentName fn)) mfpl fb) -> do fo <- interpret f funcAlreadyDeclared <- hasBinding env fn if (not funcAlreadyDeclared) then createMutableBinding env fn (Just configurableBindings) else do if False then return () else return () setMutableBinding env fn (inj fo) strict return () step4 :: (Functor m, Monad m) => EnvironmentRecord -> JavaScriptT m Bool step4 env = do argumentsAlreadyDeclared <- hasBinding env "arguments" return argumentsAlreadyDeclared step5 :: (Functor m, Monad m) => Bool -> LexicalEnvironment -> DeclarativeEnvironmentRecord -> Object -> List String -> List Value -> JavaScriptT m () step5 strict lex env func names args@(List as) = do argsObj <- createArgumentsObject func names args lex strict if strict then do createImmutableBindingDeclarative env "arguments" initializeImmutableBindingDeclarative env "arguments" (inj argsObj) return () else do createMutableBindingDeclarative env "arguments" Nothing setMutableBindingDeclarative env "arguments" (inj argsObj) False step6 :: (Functor m, Monad m) => Bool -> Bool -> EnvironmentRecord -> SourceElements -> JavaScriptT m () step6 strict configurableBindings env ses = do forM (extractVarDeclIdents ses) $ \(Ident (IdentName dn)) -> do varAlreadyDeclared <- hasBinding env dn when (not varAlreadyDeclared) $ do createMutableBinding env dn (Just configurableBindings) setMutableBinding env dn (inj Undefined) strict return () extractFuncDecls :: SourceElements -> [FuncDecl] extractFuncDecls (SourceElements (SourceElementFuncDecl fd)) = [fd] extractFuncDecls (SourceElements _) = [] extractFuncDecls (SourceElementsCons ses (SourceElementFuncDecl fd)) = fd:(extractFuncDecls ses) extractFuncDecls (SourceElementsCons ses _) = extractFuncDecls ses extractVarDeclIdents :: SourceElements -> [Ident] extractVarDeclIdents (SourceElementsCons ses se) = extractVarDeclIdentsSE se ++ extractVarDeclIdents ses extractVarDeclIdents (SourceElements se) = extractVarDeclIdentsSE se extractVarDeclIdentsSE (SourceElementStmt s) = extractVarDeclIdentsS s extractVarDeclIdentsSE _ = [] extractVarDeclIdentsS (StmtVar vs) = extractVarDeclIdentsVS vs extractVarDeclIdentsS _ = [] extractVarDeclIdentsVS (VarStmt vdl) = extractVarDeclIdentsVDL vdl extractVarDeclIdentsVDL (VarDeclList vd) = extractVarDeclIdentsVD vd extractVarDeclIdentsVDL (VarDeclListCons vdl vd) = extractVarDeclIdentsVD vd ++ extractVarDeclIdentsVDL vdl extractVarDeclIdentsVD (VarDecl i _) = [i] type UInt16 = Word16 type UInt32 = Word32 data Context = Context { contextLexicalEnvironment :: LexicalEnvironment , contextVariableEnvironment :: LexicalEnvironment , contextThisBinding :: Value , contextLabels :: [Ident] } deriving (Show) lexicalEnvironment :: Lens' Context LexicalEnvironment lexicalEnvironment = Lens.lens contextLexicalEnvironment (\c le -> c { contextLexicalEnvironment = le }) variableEnvironment :: Lens' Context LexicalEnvironment variableEnvironment = Lens.lens contextVariableEnvironment (\c ve -> c { contextVariableEnvironment = ve }) thisBinding :: Lens' Context Value thisBinding = Lens.lens contextThisBinding (\c t -> c { contextThisBinding = t }) labels :: Lens' Context [Ident] labels = Lens.lens contextLabels (\c ls -> c { contextLabels = ls }) inCurrentLabelSet :: Maybe Ident -> JavaScriptM Bool inCurrentLabelSet mi = do case mi of Just i -> do ls <- Lens.use $ contextStack . currentContext . labels return (i `elem` ls) _ -> return True data ContextStack = ContextStack { contextStackCurrent :: Context , contextStackStack :: [Context] } deriving (Show) currentContext :: Lens' ContextStack Context currentContext = Lens.lens contextStackCurrent (\cs c -> cs { contextStackCurrent = c }) type EnvironmentRecordHeap = Map EnvironmentRecord EnvironmentRecordInternal type DeclarativeEnvironmentRecordHeap = Map DeclarativeEnvironmentRecord DeclarativeEnvironmentRecordInternal type LexicalEnvironmentHeap = Map LexicalEnvironment LexicalEnvironmentInternal type ObjectHeap m = Map Object (ObjectInternal m) data JavaScriptState m = JavaScriptState { javaScriptStateContextStack :: ContextStack , javaScriptStateNextInternalId :: InternalId , javaScriptStateEnvironmentRecordHeap :: EnvironmentRecordHeap , javaScriptStateDeclarativeEnvironmentRecordHeap :: DeclarativeEnvironmentRecordHeap , javaScriptStateLexicalEnvironmentHeap :: LexicalEnvironmentHeap , javaScriptStateObjectHeap :: ObjectHeap m , javaScriptStateGlobalLexicalEnvironment :: LexicalEnvironment , javaScriptStateGlobalObject :: Object , javaScriptStateArrayPrototypeObject :: Object , javaScriptStateBooleanPrototypeObject :: Object , javaScriptStateDatePrototypeObject :: Object , javaScriptStateErrorPrototypeObject :: Object , javaScriptStateEvalErrorPrototypeObject :: Object , javaScriptStateRangeErrorPrototypeObject :: Object , javaScriptStateReferenceErrorPrototypeObject :: Object , javaScriptStateSyntaxErrorPrototypeObject :: Object , javaScriptStateTypeErrorPrototypeObject :: Object , javaScriptStateURIErrorPrototypeObject :: Object , javaScriptStateFunctionPrototypeObject :: Object , javaScriptStateNumberPrototypeObject :: Object , javaScriptStateObjectPrototypeObject :: Object , javaScriptStateRegExpPrototypeObject :: Object , javaScriptStateStringPrototypeObject :: Object , javaScriptStateThrowTypeErrorObject :: Object } initialState :: (Functor m, Monad m) => JavaScriptState m initialState = let ctx = Context { contextLexicalEnvironment = error "Unitialised lexical environment", contextVariableEnvironment = error "Unitialised variable environment", contextThisBinding = error "Unitialised this binding", contextLabels = [] } ctxs = ContextStack { contextStackCurrent = ctx, contextStackStack = [] } environmentRecordHeap = Map.fromList [ (globalEnvironmentRecord, globalEnvironmentRecordInternal) ] declarativeEnvironmentRecordHeap = Map.empty lexicalEnvironmentHeap = Map.fromList [ (globalLexicalEnvironment, globalLexicalEnvironmentInternal) ] objectHeap = Map.fromList [ (globalObject, globalObjectInternal) , (arrayPrototypeObject, arrayPrototypeObjectInternal) , (booleanPrototypeObject, booleanPrototypeObjectInternal) , (datePrototypeObject, datePrototypeObjectInternal) , (errorPrototypeObject, errorPrototypeObjectInternal) , (errorPrototypeToString, errorPrototypeToStringInternal) , (evalErrorPrototypeObject, evalErrorPrototypeObjectInternal) , (rangeErrorPrototypeObject, rangeErrorPrototypeObjectInternal) , (referenceErrorPrototypeObject, referenceErrorPrototypeObjectInternal) , (syntaxErrorPrototypeObject, syntaxErrorPrototypeObjectInternal) , (typeErrorPrototypeObject, typeErrorPrototypeObjectInternal) , (uriErrorPrototypeObject, uriErrorPrototypeObjectInternal) , (functionPrototypeObject, functionPrototypeObjectInternal) , (numberPrototypeObject, numberPrototypeObjectInternal) , (objectPrototypeObject, objectPrototypeObjectInternal) , (regExpPrototypeObject, regExpPrototypeObjectInternal) , (stringPrototypeObject, stringPrototypeObjectInternal) , (throwTypeErrorObject, throwTypeErrorObjectInternal) , (objectConstructor, objectConstructorInternal) , (functionConstructor, functionConstructorInternal) , (arrayConstructor, arrayConstructorInternal) , (stringConstructor, stringConstructorInternal) , (booleanConstructor, booleanConstructorInternal) , (numberConstructor, numberConstructorInternal) , (dateConstructor, dateConstructorInternal) , (regExpConstructor, regExpConstructorInternal) , (errorConstructor, errorConstructorInternal) , (evalErrorConstructor, evalErrorConstructorInternal) , (rangeErrorConstructor, rangeErrorConstructorInternal) , (referenceErrorConstructor, referenceErrorConstructorInternal) , (syntaxErrorConstructor, syntaxErrorConstructorInternal) , (typeErrorConstructor, typeErrorConstructorInternal) , (uriErrorConstructor, uriErrorConstructorInternal) , (mathObject, mathObjectInternal) , (jsonObject, jsonObjectInternal) ] globalLexicalEnvironmentInternal = LexicalEnvironmentInternal globalEnvironmentRecord Nothing globalLexicalEnvironment = LexicalEnvironment 0 globalEnvironmentRecordInternal = EnvironmentRecordInternalObject (ObjectEnvironmentRecord globalObject True) globalEnvironmentRecord = EnvironmentRecord 1 globalObject = Object 2 globalObjectInternal :: (Functor m, Monad m) => ObjectInternal m globalObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("NaN", PropertyData $ DataDescriptor { dataDescriptorValue = inj nan, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("Infinity", PropertyData $ DataDescriptor { dataDescriptorValue = inj posInf, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("undefined", PropertyData $ DataDescriptor { dataDescriptorValue = inj Undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("eval", PropertyData $ DataDescriptor { dataDescriptorValue = inj globalEval, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("parseInt", PropertyData $ DataDescriptor { dataDescriptorValue = inj globalParseInt, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("parseFloat", PropertyData $ DataDescriptor { dataDescriptorValue = inj globalParseFloat, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("isNaN", PropertyData $ DataDescriptor { dataDescriptorValue = inj globalIsNaN, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("isFinite", PropertyData $ DataDescriptor { dataDescriptorValue = inj globalIsFinite, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("decodeURI", PropertyData $ DataDescriptor { dataDescriptorValue = inj globalDecodeURI, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("decodeURIComponent", PropertyData $ DataDescriptor { dataDescriptorValue = inj globalDecodeURIComponent, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("encodeURI", PropertyData $ DataDescriptor { dataDescriptorValue = inj globalEncodeURI, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("encodeURIComponent", PropertyData $ DataDescriptor { dataDescriptorValue = inj globalEncodeURIComponent, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("Object", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("Function", PropertyData $ DataDescriptor { dataDescriptorValue = inj functionConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("Array", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("String", PropertyData $ DataDescriptor { dataDescriptorValue = inj stringConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("Boolean", PropertyData $ DataDescriptor { dataDescriptorValue = inj booleanConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("Number", PropertyData $ DataDescriptor { dataDescriptorValue = inj numberConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("Date", PropertyData $ DataDescriptor { dataDescriptorValue = inj dateConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("RegExp", PropertyData $ DataDescriptor { dataDescriptorValue = inj regExpConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("Error", PropertyData $ DataDescriptor { dataDescriptorValue = inj errorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("EvalError", PropertyData $ DataDescriptor { dataDescriptorValue = inj evalErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("RangeError", PropertyData $ DataDescriptor { dataDescriptorValue = inj rangeErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("ReferenceError", PropertyData $ DataDescriptor { dataDescriptorValue = inj referenceErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("SyntaxError", PropertyData $ DataDescriptor { dataDescriptorValue = inj syntaxErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("TypeError", PropertyData $ DataDescriptor { dataDescriptorValue = inj typeErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("URIError", PropertyData $ DataDescriptor { dataDescriptorValue = inj uriErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("Math", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathObject, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) , ("JSON", PropertyData $ DataDescriptor { dataDescriptorValue = inj jsonObject, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = True }) ], objectInternalPrototype = const $ return JSNull, objectInternalClass = "Object", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } globalEval = error "globalEval" :: Object globalParseInt = error "globalParseInt" :: Object globalParseFloat = error "globalParseFloat" :: Object globalIsNaN = error "globalIsNaN" :: Object globalIsFinite = error "globalIsFinite" :: Object globalDecodeURI = error "globalDecodeURI" :: Object globalDecodeURIComponent = error "globalDecodeURIComponent" :: Object globalEncodeURI = error "globalEncodeURI" :: Object globalEncodeURIComponent = error "globalEncodeURIComponent" :: Object arrayPrototypeObject = Object 3 arrayPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ def { dataDescriptorValue = inj $ Number 0 }) , ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toString", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeToString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toLocaleString", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeToLocaleString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("concat", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeConcat, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("join", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeJoin, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("pop", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypePop, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("push", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypePush, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("reverse", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeReverse, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("shift", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeShift, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("slice", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeSlice, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("sort", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeSort, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("splice", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeSplice, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("unshift", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeUnshift, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("indexOf", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeIndexOf, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("lastIndexOf", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeLastIndexOf, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("every", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeEvery, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("some", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeSome, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("forEach", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeForEach, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("map", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeMap, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("filter", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeFilter, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("reduce", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeReduce, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("reduceRight", PropertyData $ DataDescriptor { dataDescriptorValue = inj arrayPrototypeReduceRight, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist objectPrototypeObject), objectInternalClass = "Array", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = arrayDefineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } arrayPrototypeToString = error "arrayPrototypeToString" :: Object arrayPrototypeToLocaleString = error "arrayPrototypeToLocaleString" :: Object arrayPrototypeConcat = error "arrayPrototypeConcat" :: Object arrayPrototypeJoin = error "arrayPrototypeJoin" :: Object arrayPrototypePop = error "arrayPrototypePop" :: Object arrayPrototypePush = error "arrayPrototypePush" :: Object arrayPrototypeReverse = error "arrayPrototypeReverse" :: Object arrayPrototypeShift = error "arrayPrototypeShift" :: Object arrayPrototypeSlice = error "arrayPrototypeSlice" :: Object arrayPrototypeSort = error "arrayPrototypeSort" :: Object arrayPrototypeSplice = error "arrayPrototypeSplice" :: Object arrayPrototypeUnshift = error "arrayPrototypeUnshift" :: Object arrayPrototypeIndexOf = error "arrayPrototypeUndexOf" :: Object arrayPrototypeLastIndexOf = error "arrayPrototypeLastIndexOf" :: Object arrayPrototypeEvery = error "arrayPrototypeEvery" :: Object arrayPrototypeSome = error "arrayPrototypeSome" :: Object arrayPrototypeForEach = error "arrayPrototypeForEach" :: Object arrayPrototypeMap = error "arrayPrototypeMap" :: Object arrayPrototypeFilter = error "arrayPrototypeFilter" :: Object arrayPrototypeReduce = error "arrayPrototypeReduce" :: Object arrayPrototypeReduceRight = error "arrayPrototypeReduceRight" :: Object booleanPrototypeObject = Object 4 booleanPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj booleanConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toString", PropertyData $ DataDescriptor { dataDescriptorValue = inj booleanPrototypeToString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("valueOf", PropertyData $ DataDescriptor { dataDescriptorValue = inj booleanPrototypeValueOf, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist objectPrototypeObject), objectInternalClass = "Boolean", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Just (const $ return (inj False)), objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } booleanPrototypeToString = error "booleanPrototypeToString" :: Object booleanPrototypeValueOf = error "booleanPrototypeValueOf" :: Object datePrototypeObject = Object 5 datePrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.empty, objectInternalPrototype = const $ return (JSExist objectPrototypeObject), objectInternalClass = "Date", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Just (const $ return (inj nan)), objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } errorPrototypeObject = Object 6 errorPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj errorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("name", PropertyData $ DataDescriptor { dataDescriptorValue = inj "Error", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj "", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toString", PropertyData $ DataDescriptor { dataDescriptorValue = inj errorPrototypeToString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist objectPrototypeObject), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } errorPrototypeToString = Object 7 errorPrototypeToStringInternal :: (Functor m, Monad m) => ObjectInternal m errorPrototypeToStringInternal = propertyFunctionObject errorPrototypeToStringCallImpl 0 evalErrorPrototypeObject = Object 8 evalErrorPrototypeObjectInternal :: (Functor m, Monad m) => ObjectInternal m evalErrorPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj evalErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("name", PropertyData $ DataDescriptor { dataDescriptorValue = inj "EvalError", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj "", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist errorPrototypeObject), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } rangeErrorPrototypeObject = Object 9 rangeErrorPrototypeObjectInternal :: (Functor m, Monad m) => ObjectInternal m rangeErrorPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj rangeErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("name", PropertyData $ DataDescriptor { dataDescriptorValue = inj "RangeError", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj "", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist errorPrototypeObject), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } referenceErrorPrototypeObject = Object 10 referenceErrorPrototypeObjectInternal :: (Functor m, Monad m) => ObjectInternal m referenceErrorPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj referenceErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("name", PropertyData $ DataDescriptor { dataDescriptorValue = inj "ReferenceError", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj "", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist errorPrototypeObject), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } syntaxErrorPrototypeObject = Object 11 syntaxErrorPrototypeObjectInternal :: (Functor m, Monad m) => ObjectInternal m syntaxErrorPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj syntaxErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("name", PropertyData $ DataDescriptor { dataDescriptorValue = inj "SyntaxError", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj "", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist errorPrototypeObject), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } typeErrorPrototypeObject = Object 12 typeErrorPrototypeObjectInternal :: (Functor m, Monad m) => ObjectInternal m typeErrorPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj typeErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("name", PropertyData $ DataDescriptor { dataDescriptorValue = inj "TypeError", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj "", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist errorPrototypeObject), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } uriErrorPrototypeObject = Object 13 uriErrorPrototypeObjectInternal :: (Functor m, Monad m) => ObjectInternal m uriErrorPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj uriErrorConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("name", PropertyData $ DataDescriptor { dataDescriptorValue = inj "URIError", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj "", dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist errorPrototypeObject), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } functionPrototypeObject = Object 14 functionPrototypeObjectInternal :: (Functor m, Monad m) => ObjectInternal m functionPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ def { dataDescriptorValue = inj $ Number 0 }) , ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj functionConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toString", PropertyData $ DataDescriptor { dataDescriptorValue = inj functionPrototypeToString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("apply", PropertyData $ DataDescriptor { dataDescriptorValue = inj functionPrototypeApply, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("call", PropertyData $ DataDescriptor { dataDescriptorValue = inj functionPrototypeCall, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("bind", PropertyData $ DataDescriptor { dataDescriptorValue = inj functionPrototypeBind, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False })], objectInternalPrototype = const $ return (JSExist objectPrototypeObject), objectInternalClass = "Function", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Just functionPrototypeCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } functionPrototypeToString = error "functionPrototypeToString" :: Object functionPrototypeApply = error "functionPrototypeApply" :: Object functionPrototypeCall = error "functionPrototypeCall" :: Object functionPrototypeBind = error "functionPrototypeBind" :: Object numberPrototypeObject = Object 15 numberPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj numberConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toString", PropertyData $ DataDescriptor { dataDescriptorValue = inj numberPrototypeToString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toLocaleString", PropertyData $ DataDescriptor { dataDescriptorValue = inj numberPrototypeToLocaleString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("valueOf", PropertyData $ DataDescriptor { dataDescriptorValue = inj numberPrototypeValueOf, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toFixed", PropertyData $ DataDescriptor { dataDescriptorValue = inj numberPrototypeToFixed, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toExponential", PropertyData $ DataDescriptor { dataDescriptorValue = inj numberPrototypeToExponential, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toPrecision", PropertyData $ DataDescriptor { dataDescriptorValue = inj numberPrototypeToPrecision, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist objectPrototypeObject), objectInternalClass = "Number", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Just (const $ return (inj (Number 0))), objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } numberPrototypeToString = error "numberPrototypeToString" :: Object numberPrototypeToLocaleString = error "numberPrototypeToLocaleString" :: Object numberPrototypeValueOf = error "numberPrototypeValueOf" :: Object numberPrototypeToFixed = error "numberPrototypeToFixed" :: Object numberPrototypeToExponential = error "numberPrototypeToExponential" :: Object numberPrototypeToPrecision = error "numberPrototypeToPrecision" :: Object objectPrototypeObject = Object 16 objectPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toString", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectPrototypeToString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toLocaleString", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectPrototypeToLocaleString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("valueOf", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectPrototypeValueOf, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("hasOwnProperty", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectPrototypeHasOwnProperty, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("isPrototypeOf", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectPrototypeIsPrototypeOf, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("propertyIsEnumerable", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectPrototypeIsEnumerable, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return JSNull, objectInternalClass = "Object", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Just (const $ return (inj (Number 0))), objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } objectPrototypeToString = error "objectPrototypeToString" :: Object objectPrototypeToLocaleString = error "objectPrototypeToLocaleString" :: Object objectPrototypeValueOf = error "objectPrototypeValueOf" :: Object objectPrototypeHasOwnProperty = error "objectPrototypeHasOwnProperty" :: Object objectPrototypeIsPrototypeOf = error "objectPrototypeIsPrototypeOf" :: Object objectPrototypeIsEnumerable = error "objectPrototypeIsEnumerable" :: Object regExpPrototypeObject = Object 17 regExpPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.empty, objectInternalPrototype = const $ return (JSExist objectPrototypeObject), objectInternalClass = "RegExp", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = stringGetOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Just regExpMatchImpl, objectInternalParameterMap = Nothing } stringPrototypeObject = Object 18 stringPrototypeObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("constructor", PropertyData $ DataDescriptor { dataDescriptorValue = inj stringConstructor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toString", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeToString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("valueOf", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeValueOf, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("charAt", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeCharAt, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("charCodeAt", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeCharCodeAt, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("concat", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeConcat, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("indexOf", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeIndexOf, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("lastIndexOf", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeLastIndexOf, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("localeCompare", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeLocaleCompare, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("match", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeMatch, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("replace", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeReplace, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("search", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeSearch, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("slice", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeSlice, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("split", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeSplit, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("substring", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeSubString, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toLowerCase", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeToLowerCase, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toLocaleLowerCase", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeToLocaleLowerCase, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toUpperCase", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeToUpperCase, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("toLocaleUpperCase", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeToLocaleUpperCase, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("trim", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeTrim, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist objectPrototypeObject), objectInternalClass = "String", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = stringGetOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Just $ stringPrimitiveValueImpl (inj ""), objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } stringPrototypeToString = error "stringPrototypeToString" :: Object stringPrototypeValueOf = error "stringPrototypeValueOf" :: Object stringPrototypeCharAt = error "stringPrototypeCharAt" :: Object stringPrototypeCharCodeAt = error "stringPrototypeCharCodeAt" :: Object stringPrototypeConcat = error "stringPrototypeConcat" :: Object stringPrototypeIndexOf = error "stringPrototypeIndexOf" :: Object stringPrototypeLastIndexOf = error "stringPrototypeLastIndexOf" :: Object stringPrototypeLocaleCompare = error "stringPrototypeLocaleCompare" :: Object stringPrototypeMatch = error "stringPrototypeMatch" :: Object stringPrototypeReplace = error "stringPrototypeReplace" :: Object stringPrototypeSearch = error "stringPrototypeSearch" :: Object stringPrototypeSlice = error "stringPrototypeSlice" :: Object stringPrototypeSplit = error "stringPrototypeSplit" :: Object stringPrototypeSubString = error "stringPrototypeSubString" :: Object stringPrototypeToLowerCase = error "stringPrototypeToLowerCase" :: Object stringPrototypeToLocaleLowerCase = error "stringPrototypeToLocaleLowerCase" :: Object stringPrototypeToUpperCase = error "stringPrototypeToUpperCase" :: Object stringPrototypeToLocaleUpperCase = error "stringPrototypeToLocaleUpperCase" :: Object stringPrototypeTrim = error "stringPrototypeTrim" :: Object throwTypeErrorObject = Object 19 throwTypeErrorObjectInternal = error "throwTypeErrorObject" objectConstructor = Object 20 objectConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ def { dataDescriptorValue = inj (Number 1) }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("getPrototypeOf", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorGetPrototypeOf, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("getOwnPropertyDescriptor", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorGetOwnPropertyDescriptor, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("getOwnPropertyNames", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorGetOwnPropertyNames, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("create", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorCreate, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("defineProperty", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorDefineProperty, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("defineProperties", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorDefineProperties, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("seal", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorSeal, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("freeze", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorFreeze, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("preventExtensions", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorPreventExtensions, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("isSealed", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorIsSealed, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("isFrozen", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorIsFrozen, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("isExtensible", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorIsExtensible, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("keys", PropertyData $ DataDescriptor { dataDescriptorValue = inj objectConstructorKeys, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "Object", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Just (const $ return (inj (Number 0))), objectInternalConstruct = Just objectConstructorConstructImpl, objectInternalCall = Just objectConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } objectConstructorGetPrototypeOf = error "objectConstructorGetPrototypeOf" :: Object objectConstructorGetOwnPropertyDescriptor = error "objectConstructorGetOwnPropertyDescriptor" :: Object objectConstructorGetOwnPropertyNames = error "objectConstructorGetOwnPropertyNames" :: Object objectConstructorCreate = error "objectConstructorCreate" :: Object objectConstructorDefineProperty = error "objectConstructorDefineProperty" :: Object objectConstructorDefineProperties = error "objectConstructorDefineProperties" :: Object objectConstructorSeal = error "objectConstructorSeal" :: Object objectConstructorFreeze = error "objectConstructorFreeze" :: Object objectConstructorPreventExtensions = error "objectConstructorPreventExtensions" :: Object objectConstructorIsSealed = error "objectConstructorIsSealed" :: Object objectConstructorIsFrozen = error "objectConstructorIsFrozen" :: Object objectConstructorIsExtensible = error "objectConstructorIsExtensible" :: Object objectConstructorKeys = error "objectConstructorKeys" :: Object functionConstructor = Object 21 functionConstructorInternal :: (Functor m, Monad m) => ObjectInternal m functionConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ functionPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }), ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False })], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "Function", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just functionConstructorConstructImpl, objectInternalCall = Just functionConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } arrayConstructor = Object 22 arrayConstructorInternal :: (Functor m, Monad m) => ObjectInternal m arrayConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ arrayPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("isArray", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ arrayConstructorIsArray, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "Function", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just arrayConstructorConstructImpl, objectInternalCall = Just arrayConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } arrayConstructorIsArray = error "arrayConstructorIsArray" :: Object stringConstructor = Object 23 stringConstructorInternal :: (Functor m, Monad m) => ObjectInternal m stringConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("fromCharCode", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ stringConstructorFromCharCode, dataDescriptorWritable = True, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "String", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just stringConstructorConstructImpl, objectInternalCall = Just stringConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } stringConstructorFromCharCode = error "stringConstructorFromCharCode" :: Object booleanConstructor = Object 24 booleanConstructorInternal :: (Functor m, Monad m) => ObjectInternal m booleanConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ booleanPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "Boolean", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just booleanConstructorConstructImpl, objectInternalCall = Just booleanConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } numberConstructor = Object 25 numberConstructorInternal :: (Functor m, Monad m) => ObjectInternal m numberConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ numberPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("MAX_VALUE", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("MIN_VALUE", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("NaN", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("NEGATIVE_INFINITY", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("POSITIVE_INFINITY", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "Number", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just numberConstructorConstructImpl, objectInternalCall = Just numberConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } dateConstructor = Object 26 dateConstructorInternal = error "dateConstructorInternal" regExpConstructor = Object 27 regExpConstructorInternal = error "regExpConstructorInternal" errorConstructor = Object 28 errorConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj errorPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just errorConstructorConstructImpl, objectInternalCall = Just errorConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } evalErrorConstructor = Object 29 evalErrorConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj evalErrorPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "EvalError", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just errorConstructorConstructImpl, objectInternalCall = Just errorConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } rangeErrorConstructor = Object 30 rangeErrorConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj rangeErrorPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "RangeError", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just errorConstructorConstructImpl, objectInternalCall = Just errorConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } referenceErrorConstructor = Object 31 referenceErrorConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj referenceErrorPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "ReferenceError", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just errorConstructorConstructImpl, objectInternalCall = Just errorConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } syntaxErrorConstructor = Object 32 syntaxErrorConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj syntaxErrorPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "SyntaxError", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just errorConstructorConstructImpl, objectInternalCall = Just errorConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } typeErrorConstructor = Object 33 typeErrorConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj typeErrorPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "TypeError", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just errorConstructorConstructImpl, objectInternalCall = Just errorConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } uriErrorConstructor = Object 34 uriErrorConstructorInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj $ Number 1, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("prototype", PropertyData $ DataDescriptor { dataDescriptorValue = inj uriErrorPrototypeObject, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "URIError", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just errorConstructorConstructImpl, objectInternalCall = Just errorConstructorCallImpl, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mathObject = Object 35 mathObjectInternal :: (Functor m, Monad m) => ObjectInternal m mathObjectInternal = ObjectInternal { objectInternalProperties = Map.fromList [ ("E", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("LN10", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("LN2", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("LOG2E", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("LOG10E", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("PI", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("SQRT1_2", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("SQRT2", PropertyData $ DataDescriptor { dataDescriptorValue = undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("abs", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathAbs, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("acos", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathAcos, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("asin", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathAsin, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("atan", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathAtan, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("atan2", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathAtan2, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("ceil", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathCeil, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("cos", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathCos, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("exp", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathExp, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("floor", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathFloor, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("log", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathLog, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("max", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathMax, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("min", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathMin, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("pow", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathPow, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("random", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathRandom, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("round", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathRound, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("sin", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathSin, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("sqrt", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathSqrt, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) , ("tan", PropertyData $ DataDescriptor { dataDescriptorValue = inj mathTan, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist objectPrototypeObject), objectInternalClass = "Math", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mathAbs = error "mathAbs" :: Object mathAcos = error "mathAcos" :: Object mathAsin = error "mathAsin" :: Object mathAtan = error "mathAtan" :: Object mathAtan2 = error "mathAtan2" :: Object mathCeil = error "mathCeil" :: Object mathCos = error "mathCos" :: Object mathExp = error "mathExp" :: Object mathFloor = error "mathFloor" :: Object mathLog = error "mathLog" :: Object mathMax = error "mathMax" :: Object mathMin = error "mathMin" :: Object mathPow = error "mathPow" :: Object mathRandom = error "mathRandom" :: Object mathRound = error "mathRound" :: Object mathSin = error "mathSin" :: Object mathSqrt = error "mathSqrt" :: Object mathTan = error "mathTan" :: Object jsonObject = Object 36 jsonObjectInternal = error "jsonObjectInternal" nextInternalId = 37 propertyFunctionObject :: (Functor m, Monad m) => InternalCallType m -> Number -> ObjectInternal m propertyFunctionObject c l = ObjectInternal { objectInternalProperties = Map.fromList [ ("length", PropertyData $ DataDescriptor { dataDescriptorValue = inj l, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ], objectInternalPrototype = const $ return (JSExist functionPrototypeObject), objectInternalClass = "Function", objectInternalExtensible = const $ return True, objectInternalGet = functionGetImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Just c, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } in JavaScriptState { javaScriptStateContextStack = ctxs, javaScriptStateNextInternalId = nextInternalId, javaScriptStateEnvironmentRecordHeap = environmentRecordHeap, javaScriptStateDeclarativeEnvironmentRecordHeap = declarativeEnvironmentRecordHeap, javaScriptStateLexicalEnvironmentHeap = lexicalEnvironmentHeap, javaScriptStateObjectHeap = objectHeap, javaScriptStateGlobalLexicalEnvironment = globalLexicalEnvironment, javaScriptStateGlobalObject = globalObject, javaScriptStateArrayPrototypeObject = arrayPrototypeObject, javaScriptStateBooleanPrototypeObject = booleanPrototypeObject, javaScriptStateDatePrototypeObject = datePrototypeObject, javaScriptStateErrorPrototypeObject = errorPrototypeObject, javaScriptStateEvalErrorPrototypeObject = evalErrorPrototypeObject, javaScriptStateRangeErrorPrototypeObject = rangeErrorPrototypeObject, javaScriptStateReferenceErrorPrototypeObject = referenceErrorPrototypeObject, javaScriptStateSyntaxErrorPrototypeObject = syntaxErrorPrototypeObject, javaScriptStateTypeErrorPrototypeObject = typeErrorPrototypeObject, javaScriptStateURIErrorPrototypeObject = uriErrorPrototypeObject, javaScriptStateFunctionPrototypeObject = functionPrototypeObject, javaScriptStateNumberPrototypeObject = numberPrototypeObject, javaScriptStateObjectPrototypeObject = objectPrototypeObject, javaScriptStateRegExpPrototypeObject = regExpPrototypeObject, javaScriptStateStringPrototypeObject = stringPrototypeObject, javaScriptStateThrowTypeErrorObject = throwTypeErrorObject } pushContext :: Context -> JavaScriptM () pushContext ctx = do contextStack %= push where push :: ContextStack -> ContextStack push (ContextStack c cs) = ContextStack ctx (c:cs) popContext :: JavaScriptM () popContext = do contextStack %= pop where pop :: ContextStack -> ContextStack pop (ContextStack _ []) = error "Internal error: no context to pop" pop (ContextStack _ (c:cs)) = ContextStack c cs contextStack :: Lens' (JavaScriptState m) ContextStack contextStack = Lens.lens javaScriptStateContextStack (\jss cs -> jss { javaScriptStateContextStack = cs }) nextInternalId :: Lens' (JavaScriptState m) InternalId nextInternalId = Lens.lens javaScriptStateNextInternalId (\jss noi -> jss { javaScriptStateNextInternalId = noi }) environmentRecordHeap :: Lens' (JavaScriptState m) EnvironmentRecordHeap environmentRecordHeap = Lens.lens javaScriptStateEnvironmentRecordHeap (\jss erh -> jss { javaScriptStateEnvironmentRecordHeap = erh }) declarativeEnvironmentRecordHeap :: Lens' (JavaScriptState m) DeclarativeEnvironmentRecordHeap declarativeEnvironmentRecordHeap = Lens.lens javaScriptStateDeclarativeEnvironmentRecordHeap (\jss derh -> jss { javaScriptStateDeclarativeEnvironmentRecordHeap = derh }) lexicalEnvironmentHeap :: Lens' (JavaScriptState m) LexicalEnvironmentHeap lexicalEnvironmentHeap = Lens.lens javaScriptStateLexicalEnvironmentHeap (\jss lh -> jss { javaScriptStateLexicalEnvironmentHeap = lh }) lexicalEnvironmentInternal :: LexicalEnvironment -> Lens' (JavaScriptState m) LexicalEnvironmentInternal lexicalEnvironmentInternal i = Lens.lens (\JavaScriptState {..} -> case Map.lookup i javaScriptStateLexicalEnvironmentHeap of Nothing -> error "Internal error: can't find lexicalEnvironment environment" Just o -> o) (\jss@(JavaScriptState {..}) oi -> jss { javaScriptStateLexicalEnvironmentHeap = Map.insert i oi javaScriptStateLexicalEnvironmentHeap }) mLexicalEnvironmentInternal :: LexicalEnvironment -> Lens' (JavaScriptState m) (Maybe LexicalEnvironmentInternal) mLexicalEnvironmentInternal i = lexicalEnvironmentHeap . Lens.at i objectHeap :: Lens' (JavaScriptState m) (ObjectHeap m) objectHeap = Lens.lens javaScriptStateObjectHeap (\jss oh -> jss { javaScriptStateObjectHeap = oh }) internalObject :: Object -> Lens' (JavaScriptState m) (ObjectInternal m) internalObject i = Lens.lens (\JavaScriptState {..} -> case Map.lookup i javaScriptStateObjectHeap of Nothing -> error "Internal error: can't find object" Just o -> o) (\jss@(JavaScriptState {..}) oi -> jss { javaScriptStateObjectHeap = Map.insert i oi javaScriptStateObjectHeap }) mInternalObject :: Object -> Lens' (JavaScriptState m) (Maybe (ObjectInternal m)) mInternalObject i = objectHeap . Lens.at i globalLexicalEnvironment :: Lens' (JavaScriptState m) LexicalEnvironment globalLexicalEnvironment = Lens.lens javaScriptStateGlobalLexicalEnvironment (\jss lid -> jss { javaScriptStateGlobalLexicalEnvironment = lid }) globalObject :: Lens' (JavaScriptState m) Object globalObject = Lens.lens javaScriptStateGlobalObject (\jss oid -> jss { javaScriptStateGlobalObject = oid }) arrayPrototypeObject :: Lens' (JavaScriptState m) Object arrayPrototypeObject = Lens.lens javaScriptStateArrayPrototypeObject (\jss oid -> jss { javaScriptStateArrayPrototypeObject = oid }) booleanPrototypeObject :: Lens' (JavaScriptState m) Object booleanPrototypeObject = Lens.lens javaScriptStateBooleanPrototypeObject (\jss oid -> jss { javaScriptStateBooleanPrototypeObject = oid }) datePrototypeObject :: Lens' (JavaScriptState m) Object datePrototypeObject = Lens.lens javaScriptStateDatePrototypeObject (\jss oid -> jss { javaScriptStateDatePrototypeObject = oid }) errorPrototypeObject :: Lens' (JavaScriptState m) Object errorPrototypeObject = Lens.lens javaScriptStateErrorPrototypeObject (\jss oid -> jss { javaScriptStateErrorPrototypeObject = oid }) evalErrorPrototypeObject :: Lens' (JavaScriptState m) Object evalErrorPrototypeObject = Lens.lens javaScriptStateEvalErrorPrototypeObject (\jss oid -> jss { javaScriptStateEvalErrorPrototypeObject = oid }) rangeErrorPrototypeObject :: Lens' (JavaScriptState m) Object rangeErrorPrototypeObject = Lens.lens javaScriptStateRangeErrorPrototypeObject (\jss oid -> jss { javaScriptStateRangeErrorPrototypeObject = oid }) referenceErrorPrototypeObject :: Lens' (JavaScriptState m) Object referenceErrorPrototypeObject = Lens.lens javaScriptStateReferenceErrorPrototypeObject (\jss oid -> jss { javaScriptStateReferenceErrorPrototypeObject = oid }) syntaxErrorPrototypeObject :: Lens' (JavaScriptState m) Object syntaxErrorPrototypeObject = Lens.lens javaScriptStateSyntaxErrorPrototypeObject (\jss oid -> jss { javaScriptStateSyntaxErrorPrototypeObject = oid }) typeErrorPrototypeObject :: Lens' (JavaScriptState m) Object typeErrorPrototypeObject = Lens.lens javaScriptStateTypeErrorPrototypeObject (\jss oid -> jss { javaScriptStateTypeErrorPrototypeObject = oid }) uriErrorPrototypeObject :: Lens' (JavaScriptState m) Object uriErrorPrototypeObject = Lens.lens javaScriptStateURIErrorPrototypeObject (\jss oid -> jss { javaScriptStateURIErrorPrototypeObject = oid }) functionPrototypeObject :: Lens' (JavaScriptState m) Object functionPrototypeObject = Lens.lens javaScriptStateFunctionPrototypeObject (\jss oid -> jss { javaScriptStateFunctionPrototypeObject = oid }) numberPrototypeObject :: Lens' (JavaScriptState m) Object numberPrototypeObject = Lens.lens javaScriptStateNumberPrototypeObject (\jss oid -> jss { javaScriptStateNumberPrototypeObject = oid }) objectPrototypeObject :: Lens' (JavaScriptState m) Object objectPrototypeObject = Lens.lens javaScriptStateObjectPrototypeObject (\jss oid -> jss { javaScriptStateObjectPrototypeObject = oid }) regexpPrototypeObject :: Lens' (JavaScriptState m) Object regexpPrototypeObject = Lens.lens javaScriptStateRegExpPrototypeObject (\jss oid -> jss { javaScriptStateRegExpPrototypeObject = oid }) stringPrototypeObject :: Lens' (JavaScriptState m) Object stringPrototypeObject = Lens.lens javaScriptStateStringPrototypeObject (\jss oid -> jss { javaScriptStateStringPrototypeObject = oid }) throwTypeErrorObject :: Lens' (JavaScriptState m) Object throwTypeErrorObject = Lens.lens javaScriptStateThrowTypeErrorObject (\jss oid -> jss { javaScriptStateThrowTypeErrorObject = oid }) type JavaScriptT m = Except.ExceptT Value (State.StateT (JavaScriptState m) m) type JavaScriptM a = forall m. (Functor m, Monad m) => JavaScriptT m a runJavaScriptT :: (Functor m, Monad m) => JavaScriptState m -> JavaScriptT m a -> m (Either Value a) runJavaScriptT s a = flip State.evalStateT s $ Except.runExceptT a jsThrow :: (SubType v Value) => v -> JavaScriptM a jsThrow v = Except.throwE (inj v) type JSNullable a = a + Null pattern JSNull = Right Null pattern JSExist a = Left a type JSMaybe a = a + Undefined pattern JSNothing = Right Undefined pattern JSJust a = Left a jsMaybe :: b -> (a -> b) -> JSMaybe a -> b jsMaybe b f ma = case ma of JSJust a -> f a JSNothing -> b _ -> b type Primitive = Null + Undefined + Number + String + Bool pattern PrimitiveNull a = Left a :: Primitive pattern PrimitiveUndefined a = Right (Left a) :: Primitive pattern PrimitiveNumber a = Right (Right (Left a)) :: Primitive pattern PrimitiveString a = Right (Right (Right (Left a))) :: Primitive pattern PrimitiveBool a = Right (Right (Right (Right a))) :: Primitive type Value = Object + Primitive pattern ValueObject a = Left a :: Value pattern ValuePrimitive a = Right a :: Value pattern ValueNull a = Right (PrimitiveNull a) :: Value pattern ValueUndefined a = Right (PrimitiveUndefined a) :: Value pattern ValueNumber a = Right (PrimitiveNumber a) :: Value pattern ValueString a = Right (PrimitiveString a) :: Value pattern ValueBool a = Right (PrimitiveBool a) :: Value type CallValue = Reference + Value pattern CallValueReference a = Left a :: CallValue pattern CallValueValue a = Right a :: CallValue pattern CallValueObject a = Right (ValueObject a) :: CallValue pattern CallValuePrimitive a = Right (ValuePrimitive a) :: CallValue pattern CallValueNull a = Right (ValueNull a) :: CallValue pattern CallValueUndefined a = Right (ValueUndefined a) :: CallValue pattern CallValueNumber a = Right (ValueNumber a) :: CallValue pattern CallValueString a = Right (ValueString a) :: CallValue pattern CallValueBool a = Right (ValueBool a) :: CallValue type Spec a = EnvironmentRecord + LexicalEnvironment + PropertyIdentifier + PropertyDescriptor + Completion + List a + Reference pattern SpecEnvironmentRecord a = Left a pattern SpecLexicalEnvironment a = Right (Left a) pattern SpecPropertyIdentifier a = Right (Right (Left a)) pattern SpecPropertyDescriptor a = Right (Right (Right (Left a))) pattern SpecCompletion a = Right (Right (Right (Right (Left a)))) pattern SpecList a = Right (Right (Right (Right (Right (Left a))))) pattern SpecReference a = Right (Right (Right (Right (Right (Right a))))) type ECMA a = EnvironmentRecord + LexicalEnvironment + PropertyIdentifier + PropertyDescriptor + Completion + List a + Reference + Value pattern ECMAEnvironmentRecord a = Left a pattern ECMALexicalEnvironment a = Right (Left a) pattern ECMAPropertyIdentifier a = Right (Right (Left a)) pattern ECMAPropertyDescriptor a = Right (Right (Right (Left a))) pattern ECMACompletion a = Right (Right (Right (Right (Left a)))) pattern ECMAList a = Right (Right (Right (Right (Right (Left a))))) pattern ECMAReference a = Right (Right (Right (Right (Right (Right (Left a)))))) pattern ECMAValue a = Right (Right (Right (Right (Right (Right (Right a)))))) data Undefined = Undefined deriving (Eq, Ord, Show) data Null = Null deriving (Eq, Ord, Show) data Signum = SignumPos | SignumNeg deriving (Eq, Show) newtype Number = Number Double deriving (Eq, Floating, Fractional, Num, Ord, Real, RealFloat, RealFrac, Show) nan :: Number nan = Number (0 / 0) posInf :: Number posInf = Number (1 / 0) negInf :: Number negInf = Number ((-1) / 0) type Base = EnvironmentRecord + Object + Undefined + Number + String + Bool pattern BaseEnvironmentRecord a = Left a :: Base pattern BaseObject a = Right (Left a) :: Base pattern BaseUndefined a = Right (Right (Left a)) :: Base pattern BaseProperty a = Right (Right (Right a)) :: Base pattern BaseNumber a = Right (Right (Right (Left a))) :: Base pattern BaseString a = Right (Right (Right (Right (Left a)))) :: Base pattern BaseBool a = Right (Right (Right (Right (Right a)))) :: Base data Reference = Reference Base String Bool deriving (Eq, Show) getBase :: Reference -> Base getBase (Reference base _ _) = base getReferencedName :: Reference -> String getReferencedName (Reference _ name _) = name isStrictReference :: Reference -> Bool isStrictReference (Reference _ _ strict) = strict toPrimitiveBase :: Reference -> (EnvironmentRecord + Object + Undefined) + (Number + String + Bool) toPrimitiveBase (Reference (BaseEnvironmentRecord er) _ _) = Left (inj er) toPrimitiveBase (Reference (BaseObject o) _ _) = Left (inj o) toPrimitiveBase (Reference (BaseUndefined u) _ _) = Left (inj u) toPrimitiveBase (Reference (BaseNumber n) _ _) = Right (inj n) toPrimitiveBase (Reference (BaseString s) _ _) = Right (inj s) toPrimitiveBase (Reference (BaseBool b) _ _) = Right (inj b) isPropertyReference :: Reference -> Bool isPropertyReference ref = case toPropertyReference ref of Left _ -> False _ -> True toPropertyReference :: Reference -> (EnvironmentRecord + Undefined) + (Object + Number + String + Bool) toPropertyReference (Reference (BaseEnvironmentRecord er) _ _) = Left (inj er) toPropertyReference (Reference (BaseUndefined u) _ _) = Left (inj u) toPropertyReference (Reference (BaseObject o) _ _) = Right (inj o) toPropertyReference (Reference (BaseNumber n) _ _) = Right (inj n) toPropertyReference (Reference (BaseString s) _ _) = Right (inj s) toPropertyReference (Reference (BaseBool b) _ _) = Right (inj b) isUnresolvableReference :: Reference -> Bool isUnresolvableReference ref = case toUnresolvableReference ref of Left _ -> True _ -> False toUnresolvableReference :: Reference -> Undefined + (EnvironmentRecord + Object + Number + String + Bool) toUnresolvableReference (Reference (BaseUndefined u) _ _) = Left u toUnresolvableReference (Reference (BaseEnvironmentRecord er) _ _) = Right (inj er) toUnresolvableReference (Reference (BaseObject o) _ _) = Right (inj o) toUnresolvableReference (Reference (BaseProperty p) _ _) = Right (inj p) toUnresolvableReference (Reference (BaseNumber n) _ _) = Right (inj n) toUnresolvableReference (Reference (BaseString s) _ _) = Right (inj s) toUnresolvableReference (Reference (BaseBool b) _ _) = Right (inj b) newtype List a = List [a] deriving (Eq, Show) data CompletionType = CompletionTypeNormal | CompletionTypeBreak | CompletionTypeContinue | CompletionTypeReturn | CompletionTypeThrow deriving (Eq, Show) data Completion = Completion CompletionType (Maybe Value) (Maybe Ident) deriving (Eq, Show) data Type = TypeNumber | TypeString | TypeBoolean | TypeUndefined | TypeNull | TypeObject | TypeReference | TypeList | TypeCompletion | TypePropertyDescriptor | TypePropertyIdentifier | TypeLexicalEnvironment | TypeEnvironmentRecord deriving (Eq, Show) typeOf :: forall v a. (SubType v (ECMA a)) => v -> Type typeOf v = case (inj v :: ECMA a) of ECMAEnvironmentRecord _ -> TypeEnvironmentRecord ECMALexicalEnvironment _ -> TypeLexicalEnvironment ECMAPropertyIdentifier _ -> TypePropertyIdentifier ECMAPropertyDescriptor _ -> TypePropertyDescriptor ECMACompletion _ -> TypeCompletion ECMAList _ -> TypeList ECMAReference _ -> TypeReference ECMAValue (ValueObject _) -> TypeObject ECMAValue (ValueNull _) -> TypeNull ECMAValue (ValueUndefined _) -> TypeUndefined ECMAValue (ValueBool _) -> TypeBoolean ECMAValue (ValueString _) -> TypeString ECMAValue (ValueNumber _) -> TypeNumber getValue :: (Functor m, Monad m, SubType v CallValue) => v -> JavaScriptT m Value getValue sub = do case (inj sub :: CallValue) of CallValueValue v -> return v CallValueReference ref -> do let base = getBase ref case toUnresolvableReference ref of Left _ -> newReferenceErrorObject (Just . inj $ getReferencedName ref) >>= jsThrow Right resolvableBase -> do case resolvableBase of Right propertyBase -> do case propertyBase of Left objectBase -> do get objectBase (getReferencedName ref) Right primitiveBase -> do let p = getReferencedName ref o <- toObject (inj primitiveBase) mDesc <- getProperty o p case mDesc of JSNothing -> return $ inj Undefined JSJust (PropertyDescriptor {..}) -> do case toDataDescriptor mDesc of JSJust (DataDescriptor {..}) -> do return dataDescriptorValue JSNothing -> case propertyDescriptorGet of Nothing -> return $ inj Undefined Just getter -> do callNative getter (inj primitiveBase) (List []) Left environmentRecordBase -> do getBindingValue environmentRecordBase (getReferencedName ref) (isStrictReference ref) putValue :: (SubType v1 CallValue, SubType v2 Value) => v1 -> v2 -> JavaScriptM () putValue rv w = do case (inj rv :: CallValue) of CallValueValue _ -> newReferenceErrorObject Nothing >>= jsThrow CallValueReference ref -> do let base = getBase ref case toUnresolvableReference ref of Left _ -> do if isStrictReference ref then newReferenceErrorObject (Just . inj $ getReferencedName ref) >>= jsThrow else do global <- Lens.use globalObject put global (getReferencedName ref) (inj w) False Right resolvableBase -> do case resolvableBase of Right propertyBase -> do case propertyBase of Left objectBase -> do put objectBase (getReferencedName ref) (inj w) (isStrictReference ref) Right primitiveBase -> do let p = getReferencedName ref throw = isStrictReference ref o <- toObject (inj primitiveBase) c <- canPut o p if not c then do if throw then newTypeErrorObject Nothing >>= jsThrow else return () else do ownDesc <- getOwnProperty o p if isDataDescriptor ownDesc then if throw then newTypeErrorObject Nothing >>= jsThrow else return () else do desc <- getProperty o p case toAccessorDescriptor desc of JSJust (AccessorDescriptor {..}) -> do let JSJust setter = accessorDescriptorSet call setter (inj primitiveBase) (List [(inj w)]) return () JSNothing -> do if throw then newTypeErrorObject Nothing >>= jsThrow else return () Left environmentRecordBase -> do setMutableBinding environmentRecordBase (getReferencedName ref) (inj w) (isStrictReference ref) data Property = PropertyData DataDescriptor | PropertyAccessor AccessorDescriptor deriving (Eq, Show) data DataDescriptor = DataDescriptor { dataDescriptorValue :: Value , dataDescriptorWritable :: Bool , dataDescriptorEnumerable :: Bool , dataDescriptorConfigurable :: Bool } deriving (Eq, Show) instance Default DataDescriptor where def = DataDescriptor { dataDescriptorValue = inj Undefined, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False } data AccessorDescriptor = AccessorDescriptor { accessorDescriptorGet :: JSMaybe Object , accessorDescriptorSet :: JSMaybe Object , accessorDescriptorEnumerable :: Bool , accessorDescriptorConfigurable :: Bool } deriving (Eq, Show) instance Default AccessorDescriptor where def = AccessorDescriptor { accessorDescriptorGet = JSNothing, accessorDescriptorSet = JSNothing, accessorDescriptorEnumerable = False, accessorDescriptorConfigurable = False } data PropertyIdentifier = PropertyIdentifier String PropertyDescriptor data PropertyDescriptor = PropertyDescriptor { propertyDescriptorValue :: Maybe Value , propertyDescriptorGet :: Maybe Object , propertyDescriptorSet :: Maybe Object , propertyDescriptorWritable :: Maybe Bool , propertyDescriptorEnumerable :: Maybe Bool , propertyDescriptorConfigurable :: Maybe Bool } deriving (Eq, Show) instance Default PropertyDescriptor where def = PropertyDescriptor { propertyDescriptorValue = Nothing, propertyDescriptorGet = Nothing, propertyDescriptorSet = Nothing, propertyDescriptorWritable = Nothing, propertyDescriptorEnumerable = Nothing, propertyDescriptorConfigurable = Nothing } isAccessorDescriptor :: JSMaybe PropertyDescriptor -> Bool isAccessorDescriptor mp = case mp of JSJust PropertyDescriptor {..} -> isJust propertyDescriptorGet || isJust propertyDescriptorSet _ -> False toAccessorDescriptor :: JSMaybe PropertyDescriptor -> JSMaybe AccessorDescriptor toAccessorDescriptor mp = case mp of JSNothing -> JSNothing JSJust p@(PropertyDescriptor {..}) -> if isAccessorDescriptor mp then JSJust $ AccessorDescriptor { accessorDescriptorGet = maybe JSNothing JSJust propertyDescriptorGet, accessorDescriptorSet = maybe JSNothing JSJust propertyDescriptorSet, accessorDescriptorEnumerable = maybe False id propertyDescriptorEnumerable, accessorDescriptorConfigurable = maybe False id propertyDescriptorConfigurable } else JSNothing fromAccessorDescriptor :: AccessorDescriptor -> PropertyDescriptor fromAccessorDescriptor AccessorDescriptor {..} = PropertyDescriptor { propertyDescriptorValue = Nothing, propertyDescriptorGet = jsMaybe Nothing Just accessorDescriptorGet, propertyDescriptorSet = jsMaybe Nothing Just accessorDescriptorSet, propertyDescriptorWritable = Nothing, propertyDescriptorEnumerable = Just accessorDescriptorEnumerable, propertyDescriptorConfigurable = Just accessorDescriptorConfigurable } isDataDescriptor :: JSMaybe PropertyDescriptor -> Bool isDataDescriptor mp = case mp of JSJust (PropertyDescriptor {..}) -> isJust propertyDescriptorValue || isJust propertyDescriptorWritable JSNothing -> False toDataDescriptor :: JSMaybe PropertyDescriptor -> JSMaybe DataDescriptor toDataDescriptor mp = case mp of JSNothing -> JSNothing JSJust p@(PropertyDescriptor {..}) -> if isDataDescriptor mp then JSJust $ DataDescriptor { dataDescriptorValue = maybe (inj Undefined) id propertyDescriptorValue, dataDescriptorWritable = maybe False id propertyDescriptorWritable, dataDescriptorEnumerable = maybe False id propertyDescriptorEnumerable, dataDescriptorConfigurable = maybe False id propertyDescriptorConfigurable } else JSNothing fromDataDescriptor :: DataDescriptor -> PropertyDescriptor fromDataDescriptor DataDescriptor {..} = PropertyDescriptor { propertyDescriptorValue = Just dataDescriptorValue, propertyDescriptorGet = Nothing, propertyDescriptorSet = Nothing, propertyDescriptorWritable = Just dataDescriptorWritable, propertyDescriptorEnumerable = Just dataDescriptorEnumerable, propertyDescriptorConfigurable = Just dataDescriptorConfigurable } isGenericDescriptor :: JSMaybe PropertyDescriptor -> Bool isGenericDescriptor desc = not $ isAccessorDescriptor desc || isDataDescriptor desc fromPropertyDescriptor :: JSMaybe PropertyDescriptor -> JavaScriptM (JSMaybe Object) fromPropertyDescriptor mdesc = do o <- newObjectObject Nothing case mdesc of JSNothing -> return JSNothing JSJust desc@(PropertyDescriptor {..}) -> do if isDataDescriptor mdesc then do defineOwnProperty o "value" def { propertyDescriptorValue = propertyDescriptorValue, propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just True } False defineOwnProperty o "writable" def { propertyDescriptorValue = inj <$> propertyDescriptorWritable, propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just True } False else do defineOwnProperty o "get" def { propertyDescriptorValue = inj <$> propertyDescriptorGet, propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just True } False defineOwnProperty o "set" def { propertyDescriptorValue = inj <$> propertyDescriptorSet, propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just True } False return $ JSJust o data LexicalEnvironment = LexicalEnvironment InternalId deriving (Eq, Ord, Show) data LexicalEnvironmentInternal = LexicalEnvironmentInternal EnvironmentRecord (Maybe LexicalEnvironment) deriving (Eq, Show) environmentRecord :: Lens' LexicalEnvironmentInternal EnvironmentRecord environmentRecord = Lens.lens (\(LexicalEnvironmentInternal er _) -> er) (\(LexicalEnvironmentInternal _ mc) er -> LexicalEnvironmentInternal er mc) getIdentifierReference :: Maybe LexicalEnvironment -> String -> Bool -> JavaScriptM Reference getIdentifierReference mLex name strict = do case mLex of Nothing -> return $ Reference (inj Undefined) name strict Just lex -> do LexicalEnvironmentInternal envRec outer <- Lens.use $ lexicalEnvironmentInternal lex exists <- hasBinding envRec name if exists then return $ Reference (inj envRec) name strict else getIdentifierReference outer name strict newDeclarativeEnvironment :: Maybe LexicalEnvironment -> JavaScriptM LexicalEnvironment newDeclarativeEnvironment e = do ier <- createNextInternalId ider <- createNextInternalId ile <- createNextInternalId let decEnvRecInternal = DeclarativeEnvironmentRecordInternal { declarativeEnvironmentRecordInternalBindings = Map.empty } decEnvRec = DeclarativeEnvironmentRecord ider envrecInternal = EnvironmentRecordInternalDeclarative decEnvRec envrec = EnvironmentRecord ier envInternal = LexicalEnvironmentInternal envrec e env = LexicalEnvironment ile mEnvironmentRecordInternal envrec ?= envrecInternal mDeclarativeEnvironmentRecordInternal decEnvRec ?= decEnvRecInternal mLexicalEnvironmentInternal env ?= envInternal return env newObjectObjectEnvironment :: Object -> Maybe LexicalEnvironment -> JavaScriptM LexicalEnvironment newObjectObjectEnvironment o e = do ier <- createNextInternalId ile <- createNextInternalId let envrecInternal = EnvironmentRecordInternalObject (ObjectEnvironmentRecord o False) envrec = EnvironmentRecord ier envInternal = LexicalEnvironmentInternal envrec e env = LexicalEnvironment ile mEnvironmentRecordInternal envrec ?= envrecInternal mLexicalEnvironmentInternal env ?= envInternal return env enterGlobalContext :: Program -> JavaScriptM () enterGlobalContext program = do global <- Lens.use globalObject globalEnvironment <- Lens.use globalLexicalEnvironment contextStack . currentContext . variableEnvironment .= globalEnvironment contextStack . currentContext . lexicalEnvironment .= globalEnvironment contextStack . currentContext . thisBinding .= (inj global) declarationBindingInstantiation (CodeGlobal program) enterEvalContext :: JavaScriptM () enterEvalContext = error "enterEvalContext" enterFunctionContext :: Object -> Value -> List Value -> JavaScriptM () enterFunctionContext f thisArg args = do let strict = False thisBinding <- if strict then return thisArg else case thisArg of ValueNull _ -> do global <- Lens.use globalObject return (inj global) ValueUndefined _ -> do global <- Lens.use globalObject return (inj global) _ -> do obj <- toObject thisArg return (inj obj) lex <- scope f localEnv <- newDeclarativeEnvironment (Just lex) let ctx = Context { contextLexicalEnvironment = localEnv, contextVariableEnvironment = localEnv, contextThisBinding = thisBinding, contextLabels = [] } pushContext ctx declarationBindingInstantiation (CodeFunction f args) data EnvironmentRecord = EnvironmentRecord InternalId deriving (Eq, Ord, Show) data EnvironmentRecordInternal = EnvironmentRecordInternalDeclarative DeclarativeEnvironmentRecord | EnvironmentRecordInternalObject ObjectEnvironmentRecord deriving (Eq, Show) environmentRecordInternal :: EnvironmentRecord -> Lens' (JavaScriptState m) EnvironmentRecordInternal environmentRecordInternal i = Lens.lens (\JavaScriptState {..} -> case Map.lookup i javaScriptStateEnvironmentRecordHeap of Nothing -> error "Internal error: can't find environmentRecord" Just o -> o) (\jss@(JavaScriptState {..}) oi -> jss { javaScriptStateEnvironmentRecordHeap = Map.insert i oi javaScriptStateEnvironmentRecordHeap }) mEnvironmentRecordInternal :: EnvironmentRecord -> Lens' (JavaScriptState m) (Maybe EnvironmentRecordInternal) mEnvironmentRecordInternal i = environmentRecordHeap . Lens.at i declarativeEnvironmentRecord :: Lens' EnvironmentRecordInternal DeclarativeEnvironmentRecord declarativeEnvironmentRecord = Lens.lens (\eri -> case eri of EnvironmentRecordInternalDeclarative der -> der _ -> error "Not a declarative environment record") (\eri der -> case eri of EnvironmentRecordInternalDeclarative _ -> EnvironmentRecordInternalDeclarative der _ -> error "Not a declarative environment record") objectEnvironmentRecord :: Lens' EnvironmentRecordInternal ObjectEnvironmentRecord objectEnvironmentRecord = Lens.lens (\eri -> case eri of EnvironmentRecordInternalObject der -> der _ -> error "Not a object environment record") (\eri der -> case eri of EnvironmentRecordInternalObject _ -> EnvironmentRecordInternalObject der _ -> error "Not a object environment record") data DeclarativeEnvironmentRecord = DeclarativeEnvironmentRecord InternalId deriving (Eq, Ord, Show) data DeclarativeBinding = DeclarativeBindingMutable { declarativeBindingMutableValue :: Value , declarativeBindingMutableDelete :: Bool } | DeclarativeBindingImmutable { declarativeBindingImmutableValue :: Value , declarativeBindingImmutableInitialised :: Bool } deriving (Eq, Show) data DeclarativeEnvironmentRecordInternal = DeclarativeEnvironmentRecordInternal { declarativeEnvironmentRecordInternalBindings :: Map String DeclarativeBinding } internalDeclarativeEnvironmentRecordBindings :: Lens' DeclarativeEnvironmentRecordInternal (Map String DeclarativeBinding) internalDeclarativeEnvironmentRecordBindings = Lens.lens declarativeEnvironmentRecordInternalBindings (\deri bs -> deri { declarativeEnvironmentRecordInternalBindings = bs }) internalDeclarativeEnvironmentRecordBinding :: String -> Lens' DeclarativeEnvironmentRecordInternal (Maybe DeclarativeBinding) internalDeclarativeEnvironmentRecordBinding n = internalDeclarativeEnvironmentRecordBindings . Lens.at n declarativeEnvironmentRecordInternal :: DeclarativeEnvironmentRecord -> Lens' (JavaScriptState m) DeclarativeEnvironmentRecordInternal declarativeEnvironmentRecordInternal i = Lens.lens (\JavaScriptState {..} -> case Map.lookup i javaScriptStateDeclarativeEnvironmentRecordHeap of Nothing -> error "Internal error: can't find declarativeEnvironmentRecord" Just o -> o) (\jss@(JavaScriptState {..}) oi -> jss { javaScriptStateDeclarativeEnvironmentRecordHeap = Map.insert i oi javaScriptStateDeclarativeEnvironmentRecordHeap }) mDeclarativeEnvironmentRecordInternal :: DeclarativeEnvironmentRecord -> Lens' (JavaScriptState m) (Maybe DeclarativeEnvironmentRecordInternal) mDeclarativeEnvironmentRecordInternal i = declarativeEnvironmentRecordHeap . Lens.at i data ObjectEnvironmentRecord = ObjectEnvironmentRecord { objectEnvironmentRecordBindingObject :: Object , objectEnvironmentRecordProvideThis :: Bool } deriving (Eq, Show) hasBinding :: EnvironmentRecord -> String -> JavaScriptM Bool hasBinding er n = do eri <- Lens.use $ environmentRecordInternal er case eri of EnvironmentRecordInternalDeclarative der -> hasBindingDeclarative der n EnvironmentRecordInternalObject oer -> hasBindingObject oer n hasBindingDeclarative :: DeclarativeEnvironmentRecord -> String -> JavaScriptM Bool hasBindingDeclarative envRec n = do deri <- Lens.use $ declarativeEnvironmentRecordInternal envRec let bindings = declarativeEnvironmentRecordInternalBindings deri return $ Map.member n bindings hasBindingObject :: ObjectEnvironmentRecord -> String -> JavaScriptM Bool hasBindingObject envRec n = do let bindings = objectEnvironmentRecordBindingObject envRec hasProperty bindings n createMutableBinding :: EnvironmentRecord -> String -> Maybe Bool -> JavaScriptM () createMutableBinding er n d = do eri <- Lens.use $ environmentRecordInternal er case eri of EnvironmentRecordInternalDeclarative der -> createMutableBindingDeclarative der n d EnvironmentRecordInternalObject oer -> createMutableBindingObject oer n d createMutableBindingDeclarative :: DeclarativeEnvironmentRecord -> String -> Maybe Bool -> JavaScriptM () createMutableBindingDeclarative envRec n d = do let markDel = maybe False id d binding = DeclarativeBindingMutable (inj Undefined) markDel declarativeEnvironmentRecordInternal envRec . internalDeclarativeEnvironmentRecordBinding n ?= binding createMutableBindingObject :: ObjectEnvironmentRecord -> String -> Maybe Bool -> JavaScriptM () createMutableBindingObject envRec n d = do let bindings = objectEnvironmentRecordBindingObject envRec configValue = if d == Just True then True else False desc = def { propertyDescriptorValue = Just (inj Undefined), propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just configValue } defineOwnProperty bindings n desc True return () setMutableBinding :: EnvironmentRecord -> String -> Value -> Bool -> JavaScriptM () setMutableBinding er n v s = do eri <- Lens.use $ environmentRecordInternal er case eri of EnvironmentRecordInternalDeclarative der -> setMutableBindingDeclarative der n v s EnvironmentRecordInternalObject oer -> setMutableBindingObject oer n v s setMutableBindingDeclarative :: DeclarativeEnvironmentRecord -> String -> Value -> Bool -> JavaScriptM () setMutableBindingDeclarative envRec n v s = do binding <- Lens.use $ declarativeEnvironmentRecordInternal envRec . internalDeclarativeEnvironmentRecordBinding n case binding of Nothing -> error "Internal error: setMutableBindingDeclarative assert failed" Just (DeclarativeBindingMutable _ d) -> do let binding = DeclarativeBindingMutable v d declarativeEnvironmentRecordInternal envRec . internalDeclarativeEnvironmentRecordBinding n ?= binding Just (DeclarativeBindingImmutable {}) -> if s then newTypeErrorObject Nothing >>= jsThrow else return () setMutableBindingObject :: ObjectEnvironmentRecord -> String -> Value -> Bool -> JavaScriptM () setMutableBindingObject envRec n v s = do let bindings = objectEnvironmentRecordBindingObject envRec put bindings n v s getBindingValue :: EnvironmentRecord -> String -> Bool -> JavaScriptM Value getBindingValue er n s = do eri <- Lens.use $ environmentRecordInternal er case eri of EnvironmentRecordInternalDeclarative der -> getBindingValueDeclarative der n s EnvironmentRecordInternalObject oer -> getBindingValueObject oer n s getBindingValueDeclarative :: DeclarativeEnvironmentRecord -> String -> Bool -> JavaScriptM Value getBindingValueDeclarative envRec n s = do binding <- Lens.use $ declarativeEnvironmentRecordInternal envRec . internalDeclarativeEnvironmentRecordBinding n case binding of Nothing -> error "Internal error: getBindingValueDeclarative assert failed" Just (DeclarativeBindingImmutable v False) -> if not s then return (inj Undefined) else newReferenceErrorObject (Just . inj $ s) >>= jsThrow Just (DeclarativeBindingImmutable v _) -> return v Just (DeclarativeBindingMutable v _) -> return v getBindingValueObject :: ObjectEnvironmentRecord -> String -> Bool -> JavaScriptM Value getBindingValueObject envRec n s = do let bindings = objectEnvironmentRecordBindingObject envRec value <- hasProperty bindings n if not value then do if not s then return (inj Undefined) else newReferenceErrorObject (Just . inj $ s) >>= jsThrow else get bindings n deleteBinding :: EnvironmentRecord -> String -> JavaScriptM Bool deleteBinding er n = do eri <- Lens.use $ environmentRecordInternal er case eri of EnvironmentRecordInternalDeclarative der -> deleteBindingDeclarative der n EnvironmentRecordInternalObject oer -> deleteBindingObject oer n deleteBindingDeclarative :: DeclarativeEnvironmentRecord -> String -> JavaScriptM Bool deleteBindingDeclarative envRec n = do binding <- Lens.use $ declarativeEnvironmentRecordInternal envRec . internalDeclarativeEnvironmentRecordBinding n case binding of Nothing -> return True Just (DeclarativeBindingMutable _ True) -> do declarativeEnvironmentRecordInternal envRec . internalDeclarativeEnvironmentRecordBinding n .= Nothing return True _ -> return False deleteBindingObject :: ObjectEnvironmentRecord -> String -> JavaScriptM Bool deleteBindingObject envRec n = do let bindings = objectEnvironmentRecordBindingObject envRec delete bindings n False implicitThisValue :: EnvironmentRecord -> JavaScriptM Value implicitThisValue er = do eri <- Lens.use $ environmentRecordInternal er case eri of EnvironmentRecordInternalDeclarative der -> implicitThisValueDeclarative der EnvironmentRecordInternalObject oer -> implicitThisValueObject oer implicitThisValueDeclarative :: DeclarativeEnvironmentRecord -> JavaScriptM Value implicitThisValueDeclarative _ = return (inj Undefined) implicitThisValueObject :: ObjectEnvironmentRecord -> JavaScriptM Value implicitThisValueObject envRec = do if objectEnvironmentRecordProvideThis envRec then return $ inj $ objectEnvironmentRecordBindingObject envRec else return $ inj Undefined createImmutableBindingDeclarative :: DeclarativeEnvironmentRecord -> String -> JavaScriptM () createImmutableBindingDeclarative envRec n = do let binding = DeclarativeBindingImmutable (inj Undefined) False declarativeEnvironmentRecordInternal envRec . internalDeclarativeEnvironmentRecordBinding n ?= binding initializeImmutableBindingDeclarative :: DeclarativeEnvironmentRecord -> String -> Value -> JavaScriptM () initializeImmutableBindingDeclarative envRec n v = do let binding = DeclarativeBindingImmutable v True declarativeEnvironmentRecordInternal envRec . internalDeclarativeEnvironmentRecordBinding n ?= binding data MatchResult = MatchResult type InternalId = Int data Object = Object InternalId deriving (Eq, Ord, Show) type InternalPropertiesType = Map String Property type InternalPrototypeType m = Object -> JavaScriptT m (JSNullable Object) type InternalClassType = String type InternalExtensibleType m = Object -> JavaScriptT m Bool type InternalGetType m = Object -> String -> JavaScriptT m Value type InternalGetOwnPropertyType m = Object -> String -> JavaScriptT m (JSMaybe PropertyDescriptor) type InternalGetPropertyType m = Object -> String -> JavaScriptT m (JSMaybe PropertyDescriptor) type InternalPutType m = Object -> String -> Value -> Bool -> JavaScriptT m () type InternalCanPutType m = Object -> String -> JavaScriptT m Bool type InternalHasPropertyType m = Object -> String -> JavaScriptT m Bool type InternalDeleteType m = Object -> String -> Bool -> JavaScriptT m Bool type InternalDefaultValueType m = Object -> Maybe Hint -> JavaScriptT m Primitive type InternalDefineOwnPropertyType m = Object -> String -> PropertyDescriptor -> Bool -> JavaScriptT m Bool type InternalPrimitiveValueType m = Object -> JavaScriptT m Primitive type InternalConstructType m = Object -> List Value -> JavaScriptT m Object type InternalCallType m = Object -> Value -> List Value -> JavaScriptT m CallValue type InternalCallNativeType m = Object -> Value -> List Value -> JavaScriptT m Value type InternalHasInstanceType m = Object -> Value -> JavaScriptT m Bool type InternalScopeType m = Object -> JavaScriptT m LexicalEnvironment type InternalFormalParametersType m = Object -> JavaScriptT m (List String) type InternalCodeType m = Object -> JavaScriptT m FuncBody type InternalTargetFunctionType m = Object -> JavaScriptT m Object type InternalBoundThisType m = Object -> JavaScriptT m Value type InternalBoundArgumentsType m = Object -> JavaScriptT m (List Value) type InternalMatchType m = Object -> String -> Int -> JavaScriptT m MatchResult type InternalParameterMapType m = Object -> JavaScriptT m Object data ObjectInternal m = ObjectInternal { objectInternalProperties :: InternalPropertiesType , objectInternalPrototype :: InternalPrototypeType m , objectInternalClass :: InternalClassType , objectInternalExtensible :: InternalExtensibleType m , objectInternalGet :: InternalGetType m , objectInternalGetOwnProperty :: InternalGetOwnPropertyType m , objectInternalGetProperty :: InternalGetPropertyType m , objectInternalPut :: InternalPutType m , objectInternalCanPut :: InternalCanPutType m , objectInternalHasProperty :: InternalHasPropertyType m , objectInternalDelete :: InternalDeleteType m , objectInternalDefaultValue :: InternalDefaultValueType m , objectInternalDefineOwnProperty :: InternalDefineOwnPropertyType m , objectInternalPrimitiveValue :: Maybe (InternalPrimitiveValueType m) , objectInternalConstruct :: Maybe (InternalConstructType m) , objectInternalCall :: Maybe (InternalCallType m) , objectInternalHasInstance :: Maybe (InternalHasInstanceType m) , objectInternalScope :: Maybe (InternalScopeType m) , objectInternalFormalParameters :: Maybe (InternalFormalParametersType m) , objectInternalCode :: Maybe (InternalCodeType m) , objectInternalTargetFunction :: Maybe (InternalTargetFunctionType m) , objectInternalBoundThis :: Maybe (InternalBoundThisType m) , objectInternalBoundArguments :: Maybe (InternalBoundArgumentsType m) , objectInternalMatch :: Maybe (InternalMatchType m) , objectInternalParameterMap :: Maybe (InternalParameterMapType m) } internalProperties :: Lens' (ObjectInternal m) InternalPropertiesType internalProperties = Lens.lens objectInternalProperties (\oi ps -> oi { objectInternalProperties = ps }) internalProperty :: String -> Lens' (ObjectInternal m) (Maybe Property) internalProperty p = internalProperties . Lens.at p properties :: Object -> Lens' (JavaScriptState m) InternalPropertiesType properties o = internalObject o . internalProperties property :: Object -> String -> Lens' (JavaScriptState m) (Maybe Property) property o p = internalObject o . internalProperty p internalPrototype :: Lens' (ObjectInternal m) (InternalPrototypeType m) internalPrototype = Lens.lens objectInternalPrototype (\oi p -> oi { objectInternalPrototype = p }) prototype :: (Functor m, Monad m) => InternalPrototypeType m prototype o = callInternalProperty o objectInternalPrototype internalClass :: Lens' (ObjectInternal m) InternalClassType internalClass = Lens.lens objectInternalClass (\oi c -> oi { objectInternalClass = c }) class' :: Object -> Lens' (JavaScriptState m) InternalClassType class' o = internalObject o . internalClass internalExtensible :: Lens' (ObjectInternal m) (InternalExtensibleType m) internalExtensible = Lens.lens objectInternalExtensible (\oi e -> oi { objectInternalExtensible = e }) extensible :: (Functor m, Monad m) => InternalExtensibleType m extensible o = callInternalProperty o objectInternalExtensible internalGet :: Lens' (ObjectInternal m) (InternalGetType m) internalGet = Lens.lens objectInternalGet (\oi g -> oi { objectInternalGet = g }) get :: (Functor m, Monad m) => InternalGetType m get o = callInternalProperty1 o objectInternalGet internalGetOwnProperty :: Lens' (ObjectInternal m) (InternalGetOwnPropertyType m) internalGetOwnProperty = Lens.lens objectInternalGetOwnProperty (\oi gop -> oi { objectInternalGetOwnProperty = gop }) getOwnProperty :: (Functor m, Monad m) => InternalGetOwnPropertyType m getOwnProperty o = callInternalProperty1 o objectInternalGetOwnProperty internalGetProperty :: Lens' (ObjectInternal m) (InternalGetPropertyType m) internalGetProperty = Lens.lens objectInternalGetProperty (\oi gp -> oi { objectInternalGetProperty = gp }) getProperty :: (Functor m, Monad m) => InternalGetPropertyType m getProperty o = callInternalProperty1 o objectInternalGetProperty internalPut :: Lens' (ObjectInternal m) (InternalPutType m) internalPut = Lens.lens objectInternalPut (\oi p -> oi { objectInternalPut = p }) put :: (Functor m, Monad m) => InternalPutType m put o = callInternalProperty3 o objectInternalPut internalCanPut :: Lens' (ObjectInternal m) (InternalCanPutType m) internalCanPut = Lens.lens objectInternalCanPut (\oi cp -> oi { objectInternalCanPut = cp }) canPut :: (Functor m, Monad m) => InternalCanPutType m canPut o = callInternalProperty1 o objectInternalCanPut internalHasProperty :: Lens' (ObjectInternal m) (InternalHasPropertyType m) internalHasProperty = Lens.lens objectInternalHasProperty (\oi hp -> oi { objectInternalHasProperty = hp }) hasProperty :: (Functor m, Monad m) => InternalHasPropertyType m hasProperty o = callInternalProperty1 o objectInternalHasProperty internalDelete :: Lens' (ObjectInternal m) (InternalDeleteType m) internalDelete = Lens.lens objectInternalDelete (\oi d -> oi { objectInternalDelete = d }) delete :: (Functor m, Monad m) => InternalDeleteType m delete o = callInternalProperty2 o objectInternalDelete internalDefaultValue :: Lens' (ObjectInternal m) (InternalDefaultValueType m) internalDefaultValue = Lens.lens objectInternalDefaultValue (\oi dv -> oi { objectInternalDefaultValue = dv }) defaultValue :: (Functor m, Monad m) => InternalDefaultValueType m defaultValue o = callInternalProperty1 o objectInternalDefaultValue internalDefineOwnProperty :: Lens' (ObjectInternal m) (InternalDefineOwnPropertyType m) internalDefineOwnProperty = Lens.lens objectInternalDefineOwnProperty (\oi dop -> oi { objectInternalDefineOwnProperty = dop }) defineOwnProperty :: (Functor m, Monad m) => InternalDefineOwnPropertyType m defineOwnProperty o = callInternalProperty3 o objectInternalDefineOwnProperty internalPrimitiveValue :: Lens' (ObjectInternal m) (Maybe (InternalPrimitiveValueType m)) internalPrimitiveValue = Lens.lens objectInternalPrimitiveValue (\oi mpv -> oi { objectInternalPrimitiveValue = mpv }) primitiveValue :: (Functor m, Monad m) => InternalPrimitiveValueType m primitiveValue o = callInternalOptionalProperty o objectInternalPrimitiveValue internalConstruct :: Lens' (ObjectInternal m) (Maybe (InternalConstructType m)) internalConstruct = Lens.lens objectInternalConstruct (\oi c -> oi { objectInternalConstruct = c }) construct :: (Functor m, Monad m) => InternalConstructType m construct o = callInternalOptionalProperty1 o objectInternalConstruct internalCall :: Lens' (ObjectInternal m) (Maybe (InternalCallType m)) internalCall = Lens.lens objectInternalCall (\oi c -> oi { objectInternalCall = c }) call :: (Functor m, Monad m) => InternalCallType m call o = callInternalOptionalProperty2 o objectInternalCall callNative :: (Functor m, Monad m) => InternalCallNativeType m callNative o t l = do rv <- callInternalOptionalProperty2 o objectInternalCall t l case prj rv of Nothing -> error "Native function can't return references" Just v -> return v hasInstance :: (Functor m, Monad m) => InternalHasInstanceType m hasInstance o = callInternalOptionalProperty1 o objectInternalHasInstance internalHasInstance :: Lens' (ObjectInternal m) (Maybe (InternalHasInstanceType m)) internalHasInstance = Lens.lens objectInternalHasInstance (\oi hi -> oi { objectInternalHasInstance = hi }) scope :: (Functor m, Monad m) => InternalScopeType m scope o = callInternalOptionalProperty o objectInternalScope internalScope :: Lens' (ObjectInternal m) (Maybe (InternalScopeType m)) internalScope = Lens.lens objectInternalScope (\oi s -> oi { objectInternalScope = s }) formalParameters :: (Functor m, Monad m) => InternalFormalParametersType m formalParameters o = callInternalOptionalProperty o objectInternalFormalParameters internalFormalParameters :: Lens' (ObjectInternal m) (Maybe (InternalFormalParametersType m)) internalFormalParameters = Lens.lens objectInternalFormalParameters (\oi fp -> oi { objectInternalFormalParameters = fp }) code :: (Functor m, Monad m) => InternalCodeType m code o = callInternalOptionalProperty o objectInternalCode internalCode :: Lens' (ObjectInternal m) (Maybe (InternalCodeType m)) internalCode = Lens.lens objectInternalCode (\oi c -> oi { objectInternalCode = c }) internalTargetFunction :: Lens' (ObjectInternal m) (Maybe (InternalTargetFunctionType m)) internalTargetFunction = Lens.lens objectInternalTargetFunction (\oi tf -> oi { objectInternalTargetFunction = tf }) internalBoundThis :: Lens' (ObjectInternal m) (Maybe (InternalBoundThisType m)) internalBoundThis = Lens.lens objectInternalBoundThis (\oi bt -> oi { objectInternalBoundThis = bt }) internalBoundArguments :: Lens' (ObjectInternal m) (Maybe (InternalBoundArgumentsType m)) internalBoundArguments = Lens.lens objectInternalBoundArguments (\oi bas -> oi { objectInternalBoundArguments = bas }) internalMatch :: Lens' (ObjectInternal m) (Maybe (InternalMatchType m)) internalMatch = Lens.lens objectInternalMatch (\oi m -> oi { objectInternalMatch = m }) internalParameterMap :: Lens' (ObjectInternal m) (Maybe (InternalParameterMapType m)) internalParameterMap = Lens.lens objectInternalParameterMap (\oi pm -> oi { objectInternalParameterMap = pm }) callInternalProperty :: (Functor m, Monad m) => Object -> (ObjectInternal m -> Object -> JavaScriptT m a) -> JavaScriptT m a callInternalProperty o p = do oi <- Lens.use $ internalObject o p oi o callInternalProperty1 :: (Functor m, Monad m) => Object -> (ObjectInternal m -> Object -> a -> JavaScriptT m b) -> a -> JavaScriptT m b callInternalProperty1 o p a = do oi <- Lens.use $ internalObject o p oi o a callInternalProperty2 :: (Functor m, Monad m) => Object -> (ObjectInternal m -> Object -> a -> b -> JavaScriptT m c) -> a -> b -> JavaScriptT m c callInternalProperty2 o p a b = do oi <- Lens.use $ internalObject o p oi o a b callInternalProperty3 :: (Functor m, Monad m) => Object -> (ObjectInternal m -> Object -> a -> b -> c -> JavaScriptT m d) -> a -> b -> c -> JavaScriptT m d callInternalProperty3 o p a b c = do oi <- Lens.use $ internalObject o p oi o a b c callInternalOptionalProperty :: (Functor m, Monad m) => Object -> (ObjectInternal m -> Maybe (Object -> JavaScriptT m a)) -> JavaScriptT m a callInternalOptionalProperty o p = do oi <- Lens.use $ internalObject o case p oi of Just op -> op o Nothing -> newTypeErrorObject Nothing >>= jsThrow callInternalOptionalProperty1 :: (Functor m, Monad m) => Object -> (ObjectInternal m -> Maybe (Object -> a -> JavaScriptT m b)) -> a -> JavaScriptT m b callInternalOptionalProperty1 o p a = do oi <- Lens.use $ internalObject o case p oi of Just op -> op o a Nothing -> newTypeErrorObject Nothing >>= jsThrow callInternalOptionalProperty2 :: (Functor m, Monad m) => Object -> (ObjectInternal m -> Maybe (Object -> a -> b -> JavaScriptT m c)) -> a -> b -> JavaScriptT m c callInternalOptionalProperty2 o p a b = do oi <- Lens.use $ internalObject o case p oi of Just op -> op o a b Nothing -> newTypeErrorObject Nothing >>= jsThrow callInternalOptionalProperty3 :: (Functor m, Monad m) => Object -> (ObjectInternal m -> Maybe (Object -> a -> b -> c -> JavaScriptT m d)) -> a -> b -> c -> JavaScriptT m d callInternalOptionalProperty3 o p a b c = do oi <- Lens.use $ internalObject o case p oi of Just op -> op o a b c Nothing -> newTypeErrorObject Nothing >>= jsThrow getOwnPropertyImpl :: Object -> String -> JavaScriptM (JSMaybe PropertyDescriptor) getOwnPropertyImpl o p = do oi@(ObjectInternal {..}) <- Lens.use $ internalObject o case Map.lookup p objectInternalProperties of Just x -> do case x of PropertyData (DataDescriptor {..}) -> do return $ JSJust def { propertyDescriptorValue = Just dataDescriptorValue , propertyDescriptorWritable = Just dataDescriptorWritable , propertyDescriptorEnumerable = Just dataDescriptorEnumerable , propertyDescriptorConfigurable = Just dataDescriptorConfigurable } PropertyAccessor (AccessorDescriptor {..}) -> do return $ JSJust def { propertyDescriptorGet = jsMaybe Nothing Just accessorDescriptorGet , propertyDescriptorSet = jsMaybe Nothing Just accessorDescriptorSet , propertyDescriptorEnumerable = Just accessorDescriptorEnumerable , propertyDescriptorConfigurable = Just accessorDescriptorConfigurable } Nothing -> return JSNothing getPropertyImpl :: Object -> String -> JavaScriptM (JSMaybe PropertyDescriptor) getPropertyImpl o p = do prop <- getOwnProperty o p case prop of JSJust _ -> return prop JSNothing -> do proto <- prototype o case proto of JSNull -> return JSNothing JSExist po -> do getProperty po p getImpl :: Object -> String -> JavaScriptM Value getImpl o p = do mDesc <- getProperty o p case mDesc of JSNothing -> return $ inj Undefined JSJust desc@(PropertyDescriptor {..}) -> do case toDataDescriptor mDesc of JSJust DataDescriptor {..} -> return dataDescriptorValue JSNothing -> do case propertyDescriptorGet of Nothing -> return $ inj Undefined Just getter -> callNative getter (inj o) (List []) canPutImpl :: Object -> String -> JavaScriptM Bool canPutImpl o p = do mDesc <- getOwnProperty o p case mDesc of JSJust desc@(PropertyDescriptor {..}) -> do case toAccessorDescriptor mDesc of JSJust AccessorDescriptor {..} -> do case accessorDescriptorSet of JSNothing -> return False _ -> return True _ -> return $ fromJust propertyDescriptorWritable JSNothing -> do nProto <- prototype o case nProto of JSNull -> extensible o JSExist proto -> do mInherited <- getProperty proto p case mInherited of JSNothing -> extensible o JSJust inherited@(PropertyDescriptor {..}) -> do if isAccessorDescriptor mInherited then do case propertyDescriptorSet of Nothing -> return False _ -> return True else do e <- extensible o if not e then return False else return $ fromJust propertyDescriptorWritable putImpl :: Object -> String -> Value -> Bool -> JavaScriptM () putImpl o p v throw = do c <- canPut o p if not c then do if throw then newTypeErrorObject Nothing >>= jsThrow else return () else do ownDesc <- getOwnProperty o p if isDataDescriptor ownDesc then do let valueDesc = def { propertyDescriptorValue = Just v } defineOwnProperty o p valueDesc throw return () else do desc <- getProperty o p if isAccessorDescriptor desc then do let JSJust (PropertyDescriptor {..}) = desc let setter = fromJust propertyDescriptorSet callNative setter (inj o) (List [v]) return () else do let newDesc = def { propertyDescriptorValue = Just v, propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just True } defineOwnProperty o p newDesc throw return () return () hasPropertyImpl :: Object -> String -> JavaScriptM Bool hasPropertyImpl o p = do desc <- getProperty o p case desc of JSNothing -> return False _ -> return True deleteImpl :: Object -> String -> Bool -> JavaScriptM Bool deleteImpl o p throw = do desc <- getOwnProperty o p case desc of JSNothing -> return True JSJust (PropertyDescriptor {..}) -> do if propertyDescriptorConfigurable == Just True then do return True else do if throw then newTypeErrorObject Nothing >>= jsThrow else return False data Hint = HintString | HintNumber deriving (Eq, Show) defaultValueImpl :: Object -> Maybe Hint -> JavaScriptM Primitive defaultValueImpl o (Just HintString) = do f <- get o "toString" mc <- toCallable f case mc of Just c -> do str <- call c (inj o) (List []) case prj str of Just p -> return p Nothing -> valueOfBranch Nothing -> valueOfBranch where valueOfBranch = do valueOf <- get o "valueOf" mc <- toCallable valueOf case mc of Just c -> do val <- call c (inj o) (List []) case val of CallValuePrimitive p -> return p _ -> newTypeErrorObject Nothing >>= jsThrow Nothing -> newTypeErrorObject Nothing >>= jsThrow defaultValueImpl o (Just HintNumber) = do valueOf <- get o "valueOf" mc <- toCallable valueOf case mc of Just c -> do val <- call c (inj o) (List []) case prj val of Just p -> return p Nothing -> toStringBranch Nothing -> toStringBranch where toStringBranch = do f <- get o "toString" mc <- toCallable f case mc of Just c -> do str <- call c (inj o) (List []) case str of CallValuePrimitive p -> return p _ -> newTypeErrorObject Nothing >>= jsThrow Nothing -> newTypeErrorObject Nothing >>= jsThrow defaultValueImpl o Nothing = defaultValueImpl o (Just HintNumber) functionPrototypeCallImpl :: (Monad m) => InternalCallType m functionPrototypeCallImpl _ _ _ = return (inj Undefined) newFunctionObject :: Maybe FormalParamList -> FuncBody -> LexicalEnvironment -> Bool -> JavaScriptM Object newFunctionObject mfpl fb scope strict = do i <- createNextInternalId function <- Lens.use functionPrototypeObject let f = Object i names = case mfpl of Just fpl -> foldFormalParamList (\(Ident (IdentName s)) -> (s:)) [] fpl Nothing -> [] len = length names oi = ObjectInternal { objectInternalProperties = Map.empty, objectInternalPrototype = const $ return (JSExist function), objectInternalClass = "Function", objectInternalExtensible = const $ return True, objectInternalGet = functionGetImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Just functionConstructImpl, objectInternalCall = Just functionCallImpl, objectInternalHasInstance = Just functionHasInstanceImpl, objectInternalScope = Just $ const $ return scope, objectInternalFormalParameters = Just $ const $ return $ List names, objectInternalCode = Just $ const $ return fb, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject f ?= oi defineOwnProperty f "length" def { propertyDescriptorValue = Just $ inj (Number $ fromIntegral len), propertyDescriptorWritable = Just False, propertyDescriptorEnumerable = Just False, propertyDescriptorConfigurable = Just False } False proto <- newObjectObject Nothing defineOwnProperty proto "constructor" def { propertyDescriptorValue = Just $ inj f, propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just False, propertyDescriptorConfigurable = Just True } False defineOwnProperty f "prototype" def { propertyDescriptorValue = Just $ inj proto, propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just False, propertyDescriptorConfigurable = Just False } False if strict then do thrower <- Lens.use throwTypeErrorObject defineOwnProperty f "caller" def { propertyDescriptorGet = Just thrower, propertyDescriptorSet = Just thrower, propertyDescriptorEnumerable = Just False, propertyDescriptorConfigurable = Just False } False return f else return f where foldFormalParamList f a (FormalParamList i) = f i a foldFormalParamList f a (FormalParamListCons fpl i) = f i (foldFormalParamList f a fpl) functionConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m functionConstructorCallImpl f _ args = inj <$>functionConstructorConstructImpl f args functionConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m functionConstructorConstructImpl f args = error "functionConstructorConstructImpl" functionCallImpl :: (Functor m, Monad m) => InternalCallType m functionCallImpl f this args = do fpl <- formalParameters f enterFunctionContext f this args mc <- Lens.use $ internalObject f . internalCode result <- case mc of Nothing -> return $ Completion CompletionTypeNormal (inj Undefined) Nothing Just c -> do fb <- c f interpret fb popContext case result of Completion CompletionTypeThrow (Just v) _ -> jsThrow v Completion CompletionTypeReturn (Just v) _ -> return (inj v) _ -> return (inj Undefined) functionGetImpl :: (Functor m, Monad m) => InternalGetType m functionGetImpl f p = do v <- getImpl f p return v functionConstructImpl :: (Functor m, Monad m) => InternalConstructType m functionConstructImpl f l = do i <- createNextInternalId proto <- get f "prototype" p <- case proto of ValueObject o -> return o _ -> Lens.use objectPrototypeObject let obj = Object i oi = ObjectInternal { objectInternalProperties = Map.empty, objectInternalPrototype = const $ return (JSExist p), objectInternalClass = "Object", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject f ?= oi result <- call f (inj obj) l case result of CallValueObject o -> return o _ -> return obj functionHasInstanceImpl :: (Functor m, Monad m) => InternalHasInstanceType m functionHasInstanceImpl = error "functionHasInstanceImpl" newArrayObject :: [Value] -> JavaScriptM Object newArrayObject as = do let properties = [ ("length", PropertyData $ def { dataDescriptorValue = inj $ Number (fromIntegral $ length as), dataDescriptorWritable = True, dataDescriptorEnumerable = True, dataDescriptorConfigurable = True }) ] ++ (snd $ foldl (\(n, ps) a -> (n+1, (show n, PropertyData $ def { dataDescriptorValue = a, dataDescriptorWritable = True, dataDescriptorEnumerable = True, dataDescriptorConfigurable = True }):ps)) (0 :: Int, []) as) i <- createNextInternalId let a = Object i p <- Lens.use arrayPrototypeObject let oi = ObjectInternal { objectInternalProperties = Map.fromList properties, objectInternalPrototype = const $ return (JSExist p), objectInternalClass = "Array", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = arrayDefineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject a ?= oi return a arrayConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m arrayConstructorCallImpl a _ args = inj <$> arrayConstructorConstructImpl a args arrayConstructorConstructImpl :: InternalConstructType m arrayConstructorConstructImpl a args = undefined arrayDefineOwnPropertyImpl :: (Functor m, Monad m) => InternalDefineOwnPropertyType m arrayDefineOwnPropertyImpl a p desc throw = do JSJust oldLenDesc <- getOwnProperty a "length" >>= return . toDataDescriptor oldLen <- toNumber $ dataDescriptorValue oldLenDesc if p == "length" then do case propertyDescriptorValue desc of Nothing -> defineOwnPropertyImpl a p desc throw Just v -> do newLen <- toUint32 v curLen <- toNumber v if fromIntegral newLen /= curLen then newRangeErrorObject Nothing >>= jsThrow else do let newLenDesc = desc { propertyDescriptorValue = Just (inj $ Number $ fromIntegral newLen) } if fromIntegral newLen >= oldLen then do defineOwnPropertyImpl a "length" newLenDesc throw else do if not $ dataDescriptorWritable oldLenDesc then reject else do let (newWritable, newLenDesc') = case propertyDescriptorWritable newLenDesc of Just False -> (False, newLenDesc { propertyDescriptorWritable = Just True }) _ -> (True, newLenDesc) succeeded <- defineOwnPropertyImpl a "length" newLenDesc' throw if not succeeded then return False else do r <- deleteLoop newLen oldLen newLenDesc' newWritable if not r then return r else do when (not newWritable) $ void $ defineOwnPropertyImpl a "lenght" (def { propertyDescriptorWritable = Just False }) False return True else do iai <- isArrayIndex p if iai then do index <- toUint32 p if fromIntegral index >= oldLen && dataDescriptorWritable oldLenDesc == False then reject else do succeeded <- defineOwnPropertyImpl a p desc False if not succeeded then reject else do when (fromIntegral index >= oldLen) $ void $ do let oldLenDesc' = oldLenDesc { dataDescriptorValue = inj $ Number $ fromIntegral (index + 1) } defineOwnPropertyImpl a "length" (fromDataDescriptor oldLenDesc') False return True else defineOwnPropertyImpl a p desc throw where deleteLoop :: UInt32 -> Number -> PropertyDescriptor -> Bool -> JavaScriptM Bool deleteLoop newLen oldLen newLenDesc newWritable = do if fromIntegral newLen < oldLen then do let oldLen' = oldLen - 1 deleteSucceeded <- toString oldLen >>= \s -> delete a s False if (not deleteSucceeded) then do let writable = if not newWritable then Just False else propertyDescriptorWritable newLenDesc newLenDesc' = newLenDesc { propertyDescriptorValue = Just $ inj (oldLen' + 1), propertyDescriptorWritable = writable } defineOwnPropertyImpl a "length" newLenDesc' False reject else deleteLoop newLen oldLen' newLenDesc newWritable else return True reject :: JavaScriptM Bool reject = if throw then newTypeErrorObject Nothing >>= jsThrow else return False isArrayIndex :: String -> JavaScriptM Bool isArrayIndex p = do ui <- toUint32 p c <- toString (Number $ fromIntegral ui) return $ c == p && ui /= 2 ^ (32 :: Int) - 1 newBooleanObject :: Value -> JavaScriptM Object newBooleanObject v = do i <- createNextInternalId boolean <- Lens.use booleanPrototypeObject let b = Object i oi = ObjectInternal { objectInternalProperties = Map.empty, objectInternalPrototype = const $ return (JSExist boolean), objectInternalClass = "Boolean", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Just $ const $ return $ inj (toBoolean v), objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject b ?= oi return b booleanConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m booleanConstructorCallImpl _ _ (List vs) = do case vs of (v:_) -> return . inj $ toBoolean v _ -> return (inj False) booleanConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m booleanConstructorConstructImpl _ (List vs) = do case vs of (v:_) -> newBooleanObject v _ -> newBooleanObject (inj False) newNumberObject :: Maybe Value -> JavaScriptM Object newNumberObject mv = do i <- createNextInternalId nv <- maybe (return (Number 0)) toNumber mv number <- Lens.use numberPrototypeObject let n = Object i oi = ObjectInternal { objectInternalProperties = Map.empty, objectInternalPrototype = const $ return (JSExist number), objectInternalClass = "Number", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Just $ const $ return $ inj nv, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject n ?= oi return n numberConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m numberConstructorCallImpl _ _ (List vs) = do case vs of (v:_) -> inj <$> toNumber v _ -> return . inj $ Number 0 numberConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m numberConstructorConstructImpl _ (List vs) = do case vs of (v:_) -> newNumberObject (Just v) _ -> newNumberObject Nothing newErrorObject :: Maybe Value -> JavaScriptM Object newErrorObject mv = do i <- createNextInternalId properties <- case mv of Nothing -> return [] Just (ValueUndefined _) -> return [] Just v -> do s <- toString v return [ ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj s, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ] error <- Lens.use errorPrototypeObject let n = Object i oi = ObjectInternal { objectInternalProperties = Map.fromList properties, objectInternalPrototype = const $ return (JSExist error), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject n ?= oi return n errorConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m errorConstructorCallImpl e _ args = do inj <$> errorConstructorConstructImpl e args errorConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m errorConstructorConstructImpl _ (List vs) = do case vs of (v:_) -> newErrorObject (Just v) _ -> newErrorObject Nothing errorPrototypeToStringCallImpl :: (Functor m, Monad m) => InternalCallType m errorPrototypeToStringCallImpl _ v _ = do case v of ValueObject o -> do name <- get o "name" name' <- case name of ValueUndefined _ -> return "Error" _ -> toString name msg <- get o "message" msg' <- case msg of ValueUndefined _ -> return "" _ -> toString msg if null name' then return (inj msg') else if null msg' then return (inj name') else return (inj $ name' ++ ": " ++ msg') _ -> newTypeErrorObject Nothing >>= jsThrow newEvalErrorObject :: Maybe Value -> JavaScriptM Object newEvalErrorObject mv = do i <- createNextInternalId properties <- case mv of Nothing -> return [] Just (ValueUndefined _) -> return [] Just v -> do s <- toString v return [ ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj s, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ] p <- Lens.use evalErrorPrototypeObject let n = Object i oi = ObjectInternal { objectInternalProperties = Map.fromList properties, objectInternalPrototype = const $ return (JSExist p), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject n ?= oi return n evalErrorConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m evalErrorConstructorCallImpl e _ args = do inj <$> evalErrorConstructorConstructImpl e args evalErrorConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m evalErrorConstructorConstructImpl _ (List vs) = do case vs of (v:_) -> newEvalErrorObject (Just v) _ -> newEvalErrorObject Nothing newRangeErrorObject :: Maybe Value -> JavaScriptM Object newRangeErrorObject mv = do i <- createNextInternalId properties <- case mv of Nothing -> return [] Just (ValueUndefined _) -> return [] Just v -> do s <- toString v return [ ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj s, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ] p <- Lens.use rangeErrorPrototypeObject let n = Object i oi = ObjectInternal { objectInternalProperties = Map.fromList properties, objectInternalPrototype = const $ return (JSExist p), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject n ?= oi return n rangeErrorConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m rangeErrorConstructorCallImpl e _ args = do inj <$> rangeErrorConstructorConstructImpl e args rangeErrorConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m rangeErrorConstructorConstructImpl _ (List vs) = do case vs of (v:_) -> newRangeErrorObject (Just v) _ -> newRangeErrorObject Nothing newReferenceErrorObject :: Maybe Value -> JavaScriptM Object newReferenceErrorObject mv = do i <- createNextInternalId properties <- case mv of Nothing -> return [] Just (ValueUndefined _) -> return [] Just v -> do s <- toString v return [ ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj s, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ] p <- Lens.use referenceErrorPrototypeObject let n = Object i oi = ObjectInternal { objectInternalProperties = Map.fromList properties, objectInternalPrototype = const $ return (JSExist p), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject n ?= oi return n referenceErrorConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m referenceErrorConstructorCallImpl e _ args = do inj <$> referenceErrorConstructorConstructImpl e args referenceErrorConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m referenceErrorConstructorConstructImpl _ (List vs) = do case vs of (v:_) -> newReferenceErrorObject (Just v) _ -> newReferenceErrorObject Nothing newSyntaxErrorObject :: Maybe Value -> JavaScriptM Object newSyntaxErrorObject mv = do i <- createNextInternalId properties <- case mv of Nothing -> return [] Just (ValueUndefined _) -> return [] Just v -> do s <- toString v return [ ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj s, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ] p <- Lens.use syntaxErrorPrototypeObject let n = Object i oi = ObjectInternal { objectInternalProperties = Map.fromList properties, objectInternalPrototype = const $ return (JSExist p), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject n ?= oi return n syntaxErrorConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m syntaxErrorConstructorCallImpl e _ args = do inj <$> syntaxErrorConstructorConstructImpl e args syntaxErrorConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m syntaxErrorConstructorConstructImpl _ (List vs) = do case vs of (v:_) -> newSyntaxErrorObject (Just v) _ -> newSyntaxErrorObject Nothing newTypeErrorObject :: Maybe Value -> JavaScriptM Object newTypeErrorObject mv = do i <- createNextInternalId properties <- case mv of Nothing -> return [] Just (ValueUndefined _) -> return [] Just v -> do s <- toString v return [ ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj s, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ] p <- Lens.use typeErrorPrototypeObject let n = Object i oi = ObjectInternal { objectInternalProperties = Map.fromList properties, objectInternalPrototype = const $ return (JSExist p), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject n ?= oi return n typeErrorConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m typeErrorConstructorCallImpl e _ args = do inj <$> typeErrorConstructorConstructImpl e args typeErrorConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m typeErrorConstructorConstructImpl _ (List vs) = do case vs of (v:_) -> newTypeErrorObject (Just v) _ -> newTypeErrorObject Nothing newUriErrorObject :: Maybe Value -> JavaScriptM Object newUriErrorObject mv = do i <- createNextInternalId properties <- case mv of Nothing -> return [] Just (ValueUndefined _) -> return [] Just v -> do s <- toString v return [ ("message", PropertyData $ DataDescriptor { dataDescriptorValue = inj s, dataDescriptorWritable = False, dataDescriptorEnumerable = False, dataDescriptorConfigurable = False }) ] p <- Lens.use uriErrorPrototypeObject let n = Object i oi = ObjectInternal { objectInternalProperties = Map.fromList properties, objectInternalPrototype = const $ return (JSExist p), objectInternalClass = "Error", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject n ?= oi return n uriErrorConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m uriErrorConstructorCallImpl e _ args = do inj <$> uriErrorConstructorConstructImpl e args uriErrorConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m uriErrorConstructorConstructImpl _ (List vs) = do case vs of (v:_) -> newUriErrorObject (Just v) _ -> newUriErrorObject Nothing newStringObject :: Maybe Value -> JavaScriptM Object newStringObject mv = do i <- createNextInternalId sv <- maybe (return "") toString mv string <- Lens.use stringPrototypeObject let s = Object i oi = ObjectInternal { objectInternalProperties = Map.empty, objectInternalPrototype = const $ return (JSExist string), objectInternalClass = "String", objectInternalExtensible = const $ return True, objectInternalGet = getImpl, objectInternalGetOwnProperty = stringGetOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Just $ stringPrimitiveValueImpl mv, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject s ?= oi return s stringConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m stringConstructorCallImpl s _ (List ss) = do case ss of (s:_) -> inj <$> toString s _ -> return (inj "") stringConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m stringConstructorConstructImpl s (List vs) = do case vs of (v:_) -> newStringObject (Just v) _ -> newStringObject Nothing stringGetOwnPropertyImpl :: (Functor m, Monad m) => InternalGetOwnPropertyType m stringGetOwnPropertyImpl s p = do desc <- getOwnPropertyImpl s p case desc of JSJust d -> return $ JSJust d JSNothing -> do ns <- toInteger p >>= toString . Number . fromIntegral . abs if not (ns == p) then return (inj Undefined) else do PrimitiveString str <- primitiveValue s index <- toInteger p let len = length str if fromIntegral len <= index then return (inj Undefined) else do let resultStr = [str !! fromInteger index] return $ JSJust def { propertyDescriptorValue = Just (inj resultStr), propertyDescriptorWritable = Just False, propertyDescriptorEnumerable = Just True, propertyDescriptorConfigurable = Just False } stringPrimitiveValueImpl :: (Functor m, Monad m) => Maybe Value -> InternalPrimitiveValueType m stringPrimitiveValueImpl mv _ = do case mv of Just v -> inj <$> toString v Nothing -> return (inj "") regExpMatchImpl = undefined createArgumentsObject :: Object -> List String -> List Value -> LexicalEnvironment -> Bool -> JavaScriptM Object createArgumentsObject func (List names) (List args) env strict = do let len = length args obj <- newObjectObject Nothing object <- Lens.use objectPrototypeObject internalObject obj %= \oi -> oi { objectInternalClass = "Arguments", objectInternalPrototype = const $ return (JSExist object) } defineOwnProperty obj "length" (def { propertyDescriptorValue = Just (inj (Number (fromIntegral len))), propertyDescriptorWritable = Just True, propertyDescriptorEnumerable = Just False, propertyDescriptorConfigurable = Just True }) False return obj data Code = CodeGlobal Program | CodeEval (Maybe SourceElements) | CodeFunction Object (List Value) createNextInternalId :: JavaScriptM InternalId createNextInternalId = do next <- Lens.use nextInternalId nextInternalId .= succ next return next newObjectObject :: Maybe Value -> JavaScriptM Object newObjectObject mv = case mv of Just v -> case v of ValueObject o -> do return o _ -> if typeOf v == TypeString || typeOf v == TypeBoolean || typeOf v == TypeNumber then toObject v else createObject _ -> createObject where createObject = do i <- createNextInternalId let o = Object i p <- Lens.use objectPrototypeObject let oi = ObjectInternal { objectInternalProperties = Map.empty, objectInternalPrototype = const $ return (JSExist p), objectInternalClass = "Object", objectInternalExtensible = const $ return True, objectInternalGet = functionGetImpl, objectInternalGetOwnProperty = getOwnPropertyImpl, objectInternalGetProperty = getPropertyImpl, objectInternalPut = putImpl, objectInternalCanPut = canPutImpl, objectInternalHasProperty = hasPropertyImpl, objectInternalDelete = deleteImpl, objectInternalDefaultValue = defaultValueImpl, objectInternalDefineOwnProperty = defineOwnPropertyImpl, objectInternalPrimitiveValue = Nothing, objectInternalConstruct = Nothing, objectInternalCall = Nothing, objectInternalHasInstance = Nothing, objectInternalScope = Nothing, objectInternalFormalParameters = Nothing, objectInternalCode = Nothing, objectInternalTargetFunction = Nothing, objectInternalBoundThis = Nothing, objectInternalBoundArguments = Nothing, objectInternalMatch = Nothing, objectInternalParameterMap = Nothing } mInternalObject o ?= oi return o objectConstructorCallImpl :: (Functor m, Monad m) => InternalCallType m objectConstructorCallImpl o _ lvs@(List vs) = case vs of (ValueNull _:_) -> inj <$> objectConstructorConstructImpl o lvs (ValueUndefined _:_) -> inj <$> objectConstructorConstructImpl o lvs [] -> inj <$> objectConstructorConstructImpl o lvs (v:_) -> inj <$> toObject v objectConstructorConstructImpl :: (Functor m, Monad m) => InternalConstructType m objectConstructorConstructImpl _ (List vs) = do case vs of (v:_) -> newObjectObject (Just v) _ -> newObjectObject Nothing defineOwnPropertyImpl :: (Functor m, Monad m) => InternalDefineOwnPropertyType m defineOwnPropertyImpl o p desc throw = do mCurrent <- getOwnProperty o p e <- extensible o case (mCurrent, e) of (JSNothing, False) -> reject (JSNothing, True) -> do if isGenericDescriptor (JSJust desc) || isDataDescriptor (JSJust desc) then do let dp = PropertyData DataDescriptor { dataDescriptorValue = maybe (inj Undefined) id (propertyDescriptorValue desc), dataDescriptorWritable = maybe False id (propertyDescriptorWritable desc), dataDescriptorEnumerable = maybe False id (propertyDescriptorEnumerable desc), dataDescriptorConfigurable = maybe False id (propertyDescriptorConfigurable desc) } property o p ?= dp else do let ap = PropertyAccessor AccessorDescriptor { accessorDescriptorGet = maybe JSNothing JSJust (propertyDescriptorGet desc), accessorDescriptorSet = maybe JSNothing JSJust (propertyDescriptorSet desc), accessorDescriptorEnumerable = maybe False id (propertyDescriptorEnumerable desc), accessorDescriptorConfigurable = maybe False id (propertyDescriptorConfigurable desc) } property o p ?= ap return True (JSJust current, _) -> do if (propertyDescriptorValue desc == Nothing || (sameValue <$> propertyDescriptorValue desc <*> propertyDescriptorValue current) == Just True) && (propertyDescriptorGet desc == Nothing || (sameValue <$> propertyDescriptorGet desc <*> propertyDescriptorGet current) == Just True) && (propertyDescriptorSet desc == Nothing || (sameValue <$> propertyDescriptorSet desc <*> propertyDescriptorSet current) == Just True) && (propertyDescriptorWritable desc == Nothing || (sameValue <$> propertyDescriptorWritable desc <*> propertyDescriptorWritable current) == Just True) && (propertyDescriptorEnumerable desc == Nothing || (sameValue <$> propertyDescriptorEnumerable desc <*> propertyDescriptorEnumerable current) == Just True) && (propertyDescriptorConfigurable desc == Nothing || (sameValue <$> propertyDescriptorConfigurable desc <*> propertyDescriptorConfigurable current) == Just True) then return True else if (propertyDescriptorConfigurable current == Just False) then if (propertyDescriptorConfigurable desc == Just True) then reject else if ((==) <$> (propertyDescriptorEnumerable desc) <*> (propertyDescriptorEnumerable current)) == Just False then reject else checkDescriptor current else checkDescriptor current where reject = if throw then newTypeErrorObject Nothing >>= jsThrow else return False checkDescriptor current = do if isGenericDescriptor (JSJust desc) then setValue else do case (isDataDescriptor (JSJust current), isDataDescriptor (JSJust desc)) of (cb, db) | cb /= db -> do if propertyDescriptorConfigurable current == Just False then reject else if isDataDescriptor (JSJust current) then do error "Convert B" else do error "Convert C" (True, True) -> do if propertyDescriptorConfigurable current == Just False then if propertyDescriptorWritable current == Just False && propertyDescriptorWritable desc == Just True then reject else if propertyDescriptorWritable current == Just False && propertyDescriptorWritable desc == Just True then reject else case (propertyDescriptorWritable current, propertyDescriptorValue desc, propertyDescriptorValue current) of (Just False, Just dv, Just cv) | not $ sameValue dv cv -> reject _ -> setValue else setValue _ -> do if propertyDescriptorConfigurable current == Just False then do case (propertyDescriptorSet desc, propertyDescriptorSet current) of (Just ds, Just cs) | not $ sameValue ds cs -> reject _ -> do case (propertyDescriptorSet desc, propertyDescriptorGet current) of (Just dg, Just cg) | not $ sameValue dg cg -> reject _ -> setValue else setValue setValue = do property o p %= \(Just prop) -> Just $ case prop of PropertyData prop -> PropertyData prop { dataDescriptorValue = maybe (dataDescriptorValue prop) id (propertyDescriptorValue desc), dataDescriptorWritable = maybe (dataDescriptorWritable prop) id (propertyDescriptorWritable desc), dataDescriptorEnumerable = maybe (dataDescriptorEnumerable prop) id (propertyDescriptorEnumerable desc), dataDescriptorConfigurable = maybe (dataDescriptorConfigurable prop) id (propertyDescriptorConfigurable desc) } PropertyAccessor prop -> PropertyAccessor prop { accessorDescriptorGet = maybe (accessorDescriptorGet prop) JSJust (propertyDescriptorGet desc), accessorDescriptorSet = maybe (accessorDescriptorSet prop) JSJust (propertyDescriptorSet desc), accessorDescriptorEnumerable = maybe (accessorDescriptorEnumerable prop) id (propertyDescriptorEnumerable desc), accessorDescriptorConfigurable = maybe (accessorDescriptorConfigurable prop) id (propertyDescriptorConfigurable desc) } return True toPrimitive :: (SubType v Value) => v -> Maybe Hint -> JavaScriptM Primitive toPrimitive v mpt = case inj v of ValueObject o -> defaultValue o mpt ValuePrimitive p -> return p toBoolean :: (SubType v Value) => v -> Bool toBoolean v = case (inj v :: Value) of (ValueUndefined _) -> False (ValueNull _) -> False (ValueBool b) -> b (ValueNumber n) -> if isNaN n || n == Number 0 then False else True (ValueString s) -> not $ null s (ValueObject _) -> True toNumber :: (SubType v Value) => v -> JavaScriptM Number toNumber v = case (inj v :: Value) of ValueUndefined _ -> return nan ValueNull _ -> return $ Number 0 ValueBool b -> return $ if b then Number 1 else Number 0 ValueNumber n -> return n ValueString s -> do case parseString s of Just d -> return $ Number d Nothing -> return nan ValueObject _ -> toPrimitive v (Just HintNumber) >>= toNumber toInteger :: (SubType v Value) => v -> JavaScriptM Integer toInteger v = do number <- toNumber v if isNaN number then return 0 else return $ floor (signum number) * floor (abs number) toInt32 :: (SubType v Value) => v -> JavaScriptM Int32 toInt32 v = do number <- toNumber v if isNaN number || isInfinite number || number == Number 0 then return 0 else do let posInt = floor (signum number) * floor (abs number) int32bit = posInt `mod` 2 ^ (32 :: Int) if int32bit >= 2 ^ (31 :: Int) then return $ fromInteger $ int32bit - 2 ^ (32 :: Int) else return $ fromInteger int32bit toUint32 :: (SubType v Value) => v -> JavaScriptM UInt32 toUint32 v = do number <- toNumber v if isNaN number || isInfinite number || number == Number 0 then return 0 else do let posInt = floor (signum number) * floor (abs number) int32bit = posInt `mod` 2 ^ (32 :: Int) return $ fromInteger int32bit toUint16 :: (SubType v Value) => v -> JavaScriptM UInt16 toUint16 v = do number <- toNumber v if isNaN number || isInfinite number || number == Number 0 then return 0 else do let posInt = floor (signum number) * floor (abs number) int16bit = posInt `mod` 2 ^ (16 :: Int) return $ fromInteger int16bit primitiveToString :: (SubType v Primitive) => v -> String primitiveToString p = case (inj p :: Primitive) of PrimitiveUndefined _ -> "undefined" PrimitiveNull _ -> "null" PrimitiveBool b -> if b then "true" else "false" PrimitiveNumber (Number n) -> show n PrimitiveString s -> s toString :: (SubType v Value) => v -> JavaScriptM String toString v = case (inj v :: Value) of ValuePrimitive p -> return $ primitiveToString p ValueObject _ -> toPrimitive v (Just HintString) >>= toString toObject :: Value -> JavaScriptM Object toObject v = case v of ValueUndefined _ -> newTypeErrorObject Nothing >>= jsThrow ValueNull _ -> newTypeErrorObject Nothing >>= jsThrow ValueBool b -> newBooleanObject (inj b) ValueNumber n -> newNumberObject (inj n) ValueString s -> newStringObject (inj s) ValueObject o -> return o checkObjectCoercible :: Value -> JavaScriptM () checkObjectCoercible v = void $ toObjectCoercible v toObjectCoercible :: Value -> JavaScriptM (Object + Number + String + Bool) toObjectCoercible (ValueUndefined _) = newTypeErrorObject Nothing >>= jsThrow toObjectCoercible (ValueNull _) = newTypeErrorObject Nothing >>= jsThrow toObjectCoercible (ValueObject o) = return $ inj o toObjectCoercible (ValueNumber n) = return $ inj n toObjectCoercible (ValueString s) = return $ inj s toObjectCoercible (ValueBool b) = return $ inj b isCallable :: Value -> JavaScriptM Bool isCallable v = isJust <$> toCallable v toCallable :: Value -> JavaScriptM (Maybe Object) toCallable (ValueObject o) = do ObjectInternal {..} <- Lens.use $ internalObject o if isJust objectInternalCall then return $ Just o else return Nothing toCallable _ = return Nothing sameValue :: (SubType v1 Value, SubType v2 Value) => v1 -> v2 -> Bool sameValue x y = do case (inj x :: Value, inj y :: Value) of (ValueUndefined _, ValueUndefined _) -> True (ValueNull _, ValueNull _) -> True (ValueNumber (Number nx), ValueNumber (Number ny)) -> if isNaN nx && isNaN ny then True else if nx == 0 && isNegativeZero ny || isNegativeZero nx && ny == 0 then False else if nx == ny then True else False (ValueString sx, ValueString sy) -> sx == sy (ValueBool bx, ValueBool by) -> bx == by (ValueObject ox, ValueObject oy) -> ox == oy _ -> False compare :: (SubType v1 Value, SubType v2 Value) => v1 -> v2 -> JavaScriptM Bool compare x y = do case (inj x :: Value, inj y :: Value) of (ValueUndefined _, ValueUndefined _) -> return True (ValueNull _, ValueNull _) -> return True (ValueNumber nx, ValueNumber ny) -> return (nx == ny) (ValueString sx, ValueString sy) -> return (sx == sy) (ValueBool bx, ValueBool by) -> return (bx == by) (ValueObject ox, ValueObject oy) -> return (ox == oy) (ValueNull _, ValueUndefined _) -> return True (ValueUndefined _, ValueNull _) -> return True (ValueNumber nx, ValueString sy) -> do ny <- toNumber y compare nx ny (ValueString sx, ValueNumber ny) -> do nx <- toNumber x compare nx ny (ValueBool bx, _) -> do nx <- toNumber bx compare nx y (_, ValueBool by) -> do ny <- toNumber by compare x ny (ValueString sx, ValueObject oy) -> do py <- toPrimitive oy Nothing compare sx py (ValueNumber nx, ValueObject oy) -> do py <- toPrimitive oy Nothing compare nx py (ValueObject ox, ValueString sy) -> do px <- toPrimitive ox Nothing compare px sy (ValueObject ox, ValueNumber ny) -> do px <- toPrimitive ox Nothing compare px ny _ -> return False compareStrict :: Value -> Value -> Bool compareStrict x y = do case (x, y) of (ValueUndefined _, ValueUndefined _) -> True (ValueNull _, ValueNull _) -> True (ValueNumber nx, ValueNumber ny) -> (nx == ny) (ValueString sx, ValueString sy) -> (sx == sy) (ValueBool bx, ValueBool by) -> (bx == by) (ValueObject ox, ValueObject oy) -> (ox == oy) _ -> False compareLess :: Value -> Value -> Bool -> JavaScriptM (JSMaybe Bool) compareLess x y leftFirst = do (px, py) <- if leftFirst then do px <- toPrimitive x (Just HintNumber) py <- toPrimitive y (Just HintNumber) return (px, py) else do py <- toPrimitive y (Just HintNumber) px <- toPrimitive x (Just HintNumber) return (px, py) case (px, py) of (PrimitiveString sx, PrimitiveString sy) -> do return $ JSJust (sx < sy) _ -> do nx <- toNumber px ny <- toNumber py if isNaN nx || isNaN ny then return JSNothing else return $ JSJust (nx < ny) operatorPlus :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Value operatorPlus lref rref = do lval <- getValue lref rval <- getValue rref lprim <- toPrimitive lval Nothing rprim <- toPrimitive rval Nothing if typeOf lprim == TypeString || typeOf rprim == TypeString then liftM2 (\l r -> inj $ l ++ r) (toString lprim) (toString rprim) else liftM2 (\l r -> inj $ l + r) (toNumber lprim) (toNumber rprim) operatorMinus :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Number operatorMinus lref rref = do lval <- getValue lref rval <- getValue rref lnum <- toNumber lval rnum <- toNumber rval return $ lnum - rnum operatorMult :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Number operatorMult left right = do leftValue <- getValue left rightValue <- getValue right leftNum <- toNumber leftValue rightNum <- toNumber rightValue return $ leftNum * rightNum operatorDiv :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Number operatorDiv left right = do leftValue <- getValue left rightValue <- getValue right leftNum <- toNumber leftValue rightNum <- toNumber rightValue return $ leftNum / rightNum operatorMod :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Number operatorMod left right = do leftValue <- getValue left rightValue <- getValue right leftNum <- toNumber leftValue rightNum <- toNumber rightValue return $ leftNum `mod'` rightNum operatorLeftShift :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Number operatorLeftShift left right = do lval <- getValue left rval <- getValue right lnum <- toInt32 lval rnum <- toUint32 rval let shiftCount = fromInteger . Prelude.toInteger $ rnum .&. 0x1F return $ Number $ fromIntegral $ shiftL lnum shiftCount operatorSignedRightShift :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Number operatorSignedRightShift left right = do lval <- getValue left rval <- getValue right lnum <- toInt32 lval rnum <- toUint32 rval let shiftCount = fromInteger . Prelude.toInteger $ rnum .&. 0x1F return $ Number $ fromIntegral $ shiftR lnum shiftCount operatorUnsignedRightShift :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Number operatorUnsignedRightShift left right = do lval <- getValue left rval <- getValue right lnum <- toUint32 lval rnum <- toUint32 rval let shiftCount = fromInteger . Prelude.toInteger $ rnum .&. 0x1F return $ Number $ fromIntegral $ shiftR lnum shiftCount operatorBitwiseAnd :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Number operatorBitwiseAnd left right = do lval <- getValue left rval <- getValue right lnum <- toInt32 lval rnum <- toInt32 rval return $ Number $ fromIntegral $ lnum .&. rnum operatorBitwiseXor :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Number operatorBitwiseXor left right = do lval <- getValue left rval <- getValue right lnum <- toInt32 lval rnum <- toInt32 rval return $ Number $ fromIntegral $ lnum `xor` rnum operatorBitwiseOr :: (SubType v1 CallValue, SubType v2 CallValue) => v1 -> v2 -> JavaScriptM Number operatorBitwiseOr left right = do lval <- getValue left rval <- getValue right lnum <- toInt32 lval rnum <- toInt32 rval return $ Number $ fromIntegral $ lnum .|. rnum