diff --git a/android/playground/app/src/main/assets/lite_template/case.js b/android/playground/app/src/main/assets/lite_template/case.js index 90278f05d9..1463c8d1d0 100644 --- a/android/playground/app/src/main/assets/lite_template/case.js +++ b/android/playground/app/src/main/assets/lite_template/case.js @@ -1,10 +1,72 @@ /* eslint-disable react/react-in-jsx-scope */ /* global __weex_data__, print, createElement */ + +try{ + console.log("abc in try"); +} catch(err) { + console.log("err"); +} finally{ + console.log("finally"); +} + +var a= /(a.)/g; +var b = a.exec('abc,aac, ssa2, dda'); +console.log(b); + +console.log('aabccbddBc'.match(/(bss.)/g)); + +console.log("ceil"); +console.log(Math.ceil(0.95)," == 1"); +console.log(Math.ceil(4)," == 4"); +console.log(Math.ceil(7.004)," == 8"); +console.log(Math.ceil(-0.95)," == -0"); +console.log(Math.ceil(-4)," == -4"); +console.log(Math.ceil(-7.004)," == -7"); + +console.log("floor"); +console.log(Math.floor( 45.95)," == 45"); +console.log(Math.floor( 45.05)," == 45"); +console.log(Math.floor( 4 )," == 4"); +console.log(Math.floor(-45.05)," == -46"); +console.log(Math.floor(-45.95)," == -46"); + +console.log("random"); +console.log(Math.random()); +console.log(Math.random()); +console.log(Math.random()); +console.log(Math.random()); + +console.log("max"); +console.log(Math.max(1,2,3)," == 3"); +console.log(Math.max(1,2.2, 4.2), "== 4.2"); +console.log(Math.max(1,"a"),"== null"); +console.log(Math.max(),"== INT_MIN"); + +console.log("min"); +console.log(Math.min(1,2,3)," == 1"); +console.log(Math.min(0.5,2.2, 4), "== 0.5"); +console.log(Math.min(1,"a"),"== null"); +console.log(Math.min(),"== INT_MAX"); + +var a = 3; + +console.log('start'); +switch(a){ + case 1: + console.log('switch 1'); + break; + case 2: + console.log('switch 2'); + break; + default: + console.log('default branch'); +} +console.log('end'); class Component { constructor(props) { this.props = props; } - + setState(newData) { this.state = { ...this.state, ...newData @@ -20,7 +82,7 @@ var nativeModules = {}; const registerModule = moduleName => { var sourceKeys = Object.keys(moduleName); var key; - + for (var i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; nativeModules[key] = moduleName[key]; @@ -46,12 +108,12 @@ const require = name => { loop(methods[i]); } } - log("register",methods); + console.log("register",methods); return target; }; - + const MODULE_NAME_PREFIX = '@weex-module/'; - + if (name.split(MODULE_NAME_PREFIX).length > 1) { const weexModuleName = name.split(MODULE_NAME_PREFIX)[1]; return requireModule(weexModuleName); @@ -150,12 +212,12 @@ class TipTag extends Component { super(props); } _onClick = e => { - log("click go"); + console.log("click go"); let searchParams = {}; if (this.props.data.q) { searchParams.q = this.props.data.q; } - + if (this.props.data.params && this.props.data.params.length > 0) { this.props.data.params.forEach(item => { if (item.key) { @@ -165,22 +227,22 @@ class TipTag extends Component { } if (this.props.tiptype && this.props.tiptype == 'voice_smarttips') { searchParams['voiceFrom'] = '1'; - log("se go"); + console.log("se go"); searchEvent.searchOption("searchOption", { params: searchParams }); } else { - log("se go2"); + console.log("se go2"); searchEvent.search("search", { params: searchParams }); } }; - + render() { let data = this.props.data; let tagStyle = styles.tag; - + if (!this.props.isListMode) { tagStyle = { ...styles.tag, marginLeft: 5.5, @@ -193,7 +255,7 @@ class TipTag extends Component { {data.show} ; } - + } const _tiptag_export = { @@ -205,15 +267,15 @@ const TipTag_import_default_from__WidgetInWFStyle__tiptag = _tiptag_export.defau const WidgetInWFStyle = props => { let tips = props.tips, tiptype = props.tiptype; - + if (!tips || tips.length === 0) { return null; } - + if (tips.length > 8) { tips = tips.slice(0, 8); } - + let wfTitle = {props.topic || '相关搜索'} @@ -221,7 +283,7 @@ const WidgetInWFStyle = props => { ; let wfLines = []; let tipLength = tips.length; - + function createWfLine(leftTip, rightTip) { let tag1 = ; let tag2 = rightTip ? : null; @@ -309,11 +371,11 @@ const WidgetInListStyle = props => { if (!tips || tips.length === 0) { return null; } - + if (tips.length > 8) { tips = tips.slice(0, 8); } - + const listTitle = {props.topic || '相关搜索'} @@ -327,7 +389,7 @@ const WidgetInListStyle = props => { firstLineTips.push(tipTag); } else { const firstLineCount = parseInt(tips.length / 2, 10) + tips.length % 2; - + if (index < firstLineCount) { firstLineTips.push(tipTag); } else if (index < 8) { @@ -371,7 +433,7 @@ class Widget extends Component { return {content}; } - + } const _lib_export = { @@ -400,7 +462,8 @@ class Segment extends Component { ; } - + } render(); + diff --git a/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java b/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java index 2e13921f9b..8a5408daf8 100644 --- a/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java +++ b/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java @@ -242,8 +242,13 @@ private void loadWXfromService(final String url) { public void onSuccess(WXHttpTask task) { Log.i(TAG, "into--[http:onSuccess] url:" + url); try { + Uri uri = Uri.parse(url); mConfigMap.put("bundleUrl", url); - mInstance.render(TAG, new String(task.response.data, "utf-8"), mConfigMap, null, WXRenderStrategy.APPEND_ASYNC); + if (uri.getPath().endsWith(".wlasm")){ + mInstance.render(TAG, task.response.data, mConfigMap, null); + } else { + mInstance.render(TAG, new String(task.response.data, "utf-8"), mConfigMap, null, WXRenderStrategy.APPEND_ASYNC); + } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } diff --git a/android/sdk/gradle/wrapper/gradle-wrapper.properties b/android/sdk/gradle/wrapper/gradle-wrapper.properties index 73990aa521..d64998259f 100644 --- a/android/sdk/gradle/wrapper/gradle-wrapper.properties +++ b/android/sdk/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=http://gw.alicdn.com/bao/uploaded/LB1J5WLJVXXXXcMXpXXXXXXXXXX.zip diff --git a/android/sdk/libs/armeabi-v7a/libweexcore.so b/android/sdk/libs/armeabi-v7a/libweexcore.so old mode 100644 new mode 100755 diff --git a/android/sdk/libs/armeabi/libweexcore.so b/android/sdk/libs/armeabi/libweexcore.so old mode 100644 new mode 100755 diff --git a/android/sdk/libs/x86/libweexcore.so b/android/sdk/libs/x86/libweexcore.so old mode 100644 new mode 100755 index bee91b96e4..9955dc3fca Binary files a/android/sdk/libs/x86/libweexcore.so and b/android/sdk/libs/x86/libweexcore.so differ diff --git a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java index b470d6d67e..cfa87b7e66 100644 --- a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java +++ b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java @@ -93,6 +93,7 @@ import java.util.PriorityQueue; import java.util.concurrent.ConcurrentHashMap; +import static com.taobao.weex.common.WXErrorCode.WX_ERR_RELOAD_PAGE; import static com.taobao.weex.http.WXHttpUtil.KEY_USER_AGENT; @@ -127,6 +128,8 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan private String mBundleUrl = ""; public static String requestUrl = "requestUrl"; private boolean isDestroy=false; + private boolean hasException = false; + private boolean isRenderSuccess = false; private Map mUserTrackParams; private NativeInvokeHelper mNativeInvokeHelper; private boolean isCommit=false; @@ -705,13 +708,43 @@ private void renderInternal(String pageName, WXSDKManager.getInstance().createInstance(this, template, renderOptions, jsonInitData); mRendered = true; + + + if(WXBridgeManager.getInstance().isIsRebootJscWhenWhiteScreen()) { + WXSDKManager.getInstance().postOnUiThread(new Runnable() { + @Override + public void run() { + if(isDestroy || hasException || isRenderSuccess) { + return; + } + + View containerView = getContainerView(); + if(containerView instanceof ViewGroup) { + if(0 == ((ViewGroup) containerView).getChildCount()) { + boolean isWxActivity = false; + if(mContext != null && mContext.getClass() != null) { + String name = mContext.getClass().getName(); + if(!TextUtils.isEmpty(name)) { + isWxActivity = name.contains("WXActivity"); + } + } + + if(!isWxActivity) { + onJSException(String.valueOf(WX_ERR_RELOAD_PAGE),"jsc reboot","jsc reboot"); + } + WXBridgeManager.getInstance().callReportCrashReloadPage(mInstanceId, null); + } + } + } + }, WXBridgeManager.getInstance().getRebootJscTimeout()); + } } private void renderByUrlInternal(String pageName, final String url, Map options, final String jsonInitData, - final WXRenderStrategy flag) { + WXRenderStrategy flag) { ensureRenderArchor(); pageName = wrapPageName(pageName, url); @@ -740,6 +773,16 @@ private void renderByUrlInternal(String pageName, return; } + boolean is_wlasm = false; + if (uri != null && uri.getPath()!=null) { + if(uri.getPath().endsWith(".wlasm")){ + is_wlasm = true; + } + } + if (is_wlasm){ + flag = WXRenderStrategy.DATA_RENDER_BINARY; + } + IWXHttpAdapter adapter = WXSDKManager.getInstance().getIWXHttpAdapter(); WXRequest wxRequest = new WXRequest(); @@ -1017,9 +1060,10 @@ public void onActivityCreate() { mGlobalEventReceiver=new WXGlobalEventReceiver(this); try { getContext().registerReceiver(mGlobalEventReceiver, new IntentFilter(WXGlobalEventReceiver.EVENT_ACTION)); - } catch (Exception e) { + } catch (Throwable e) { // Huawei may throw a exception if register more than 500 BroadcastReceivers WXLogUtils.e(e.getMessage()); + mGlobalEventReceiver = null; } } @@ -1265,6 +1309,7 @@ public void runOnUiThread(Runnable action) { } public void onRenderSuccess(final int width, final int height) { + isRenderSuccess = true; if (!isNewFsEnd){ getApmForInstance().arriveNewFsRenderTime(); } @@ -1298,7 +1343,7 @@ public void onRenderSuccess(final int width, final int height) { WXLogUtils.d(WXLogUtils.WEEX_PERF_TAG, mWXPerformance.toString()); } - if(!WXEnvironment.isApkDebugable()){ + if(WXEnvironment.isPerf()){ WXLogUtils.e("weex_perf",mWXPerformance.getPerfData()); } } @@ -1365,6 +1410,7 @@ public void run() { public void onJSException(final String errCode, final String function, final String exception) { getExceptionRecorder().recordReportErrorMsg("["+errCode+","+function+","+exception+"]"); + hasException = true; if (mRenderListener != null && mContext != null) { runOnUiThread(new Runnable() { @@ -2010,8 +2056,12 @@ public void onHttpFinish(WXResponse response) { String wxErrorCode = WXInstanceApm.VALUE_ERROR_CODE_DEFAULT; if (response!=null && response.originalData!=null && TextUtils.equals("200", response.statusCode)) { mApmForInstance.onStage(WXInstanceApm.KEY_PAGE_STAGES_DOWN_BUNDLE_END); - String template = new String(response.originalData); - render(pageName, template, options, jsonInitData, flag); + if (flag==WXRenderStrategy.DATA_RENDER_BINARY){ + render(pageName, response.originalData, options, jsonInitData); + } else { + String template = new String(response.originalData); + render(pageName, template, options, jsonInitData, flag); + } // check content-type } else if (TextUtils.equals(WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode(), diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java index 5785fd3c0a..531b601133 100644 --- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java +++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java @@ -162,6 +162,9 @@ public class WXBridgeManager implements Callback, BactchExecutor { // add for cloud setting, default value is false. // weexcore use single process or not private static boolean isUseSingleProcess = false; + private static boolean isRebootJscWhenWhiteScreen = false; + public final static long DEFAULT_REBOOT_JSC_TIMEOUT = 5000; + private static long rebootJscTimeout = DEFAULT_REBOOT_JSC_TIMEOUT; public enum BundType { Vue, @@ -222,7 +225,21 @@ public static WXBridgeManager getInstance() { } return mBridgeManager; } + public boolean isIsRebootJscWhenWhiteScreen() { + return isRebootJscWhenWhiteScreen; + } + + public void setIsRebootJscWhenWhiteScreen(boolean _isRebootJscWhenWhiteScreen) { + isRebootJscWhenWhiteScreen = _isRebootJscWhenWhiteScreen; + } + + public long getRebootJscTimeout() { + return rebootJscTimeout; + } + public void setRebootJscTimeout(long timeout) { + rebootJscTimeout = timeout; + } public void setUseSingleProcess(final boolean flag) { if (flag != isUseSingleProcess) { isUseSingleProcess = flag; @@ -770,21 +787,27 @@ public int callRefreshFinish(String instanceId, String callback) { } public int callReportCrashReloadPage(String instanceId, String crashFile) { + boolean isCrashFileEmpty = TextUtils.isEmpty(crashFile); try { String url = null; WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); if (instance != null) { url = instance.getBundleUrl(); } - try { - if (WXEnvironment.getApplication() != null) { - crashFile = mInitParams.getCrashFilePath() + crashFile; - Log.d("jsengine", "callReportCrashReloadPage crashFile:" + crashFile); + if(!isCrashFileEmpty) { + try { + if (WXEnvironment.getApplication() != null) { + crashFile = mInitParams.getCrashFilePath() + crashFile; + Log.d("jsengine", "callReportCrashReloadPage crashFile:" + crashFile); + } + } catch (Throwable e) { + e.printStackTrace(); } - } catch (Throwable e) { - e.printStackTrace(); + callReportCrash(crashFile, instanceId, url); + } else { + commitJscCrashAlarmMonitor(IWXUserTrackAdapter.JS_BRIDGE, WXErrorCode.WX_ERR_RELOAD_PAGE, "reboot jsc Engine", instanceId, url); } - callReportCrash(crashFile, instanceId, url); + if (reInitCount > CRASHREINIT) { return IWXBridge.INSTANCE_RENDERING_ERROR; } diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionMoveElement.java b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionMoveElement.java index 7523120103..424ee8416e 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionMoveElement.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionMoveElement.java @@ -39,9 +39,12 @@ public GraphicActionMoveElement(WXSDKInstance instance, String ref, String paren @Override public void executeAction() { WXComponent component = WXSDKManager.getInstance().getWXRenderManager().getWXComponent(getPageId(), getRef()); + if(component == null) { + return; + } WXVContainer oldParent = component.getParent(); WXComponent newParent = WXSDKManager.getInstance().getWXRenderManager().getWXComponent(getPageId(), mParentref); - if (component == null || oldParent == null + if (oldParent == null || newParent == null || !(newParent instanceof WXVContainer)) { return; } diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java index 7e519e96a2..a0a5c1dc49 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java @@ -21,6 +21,8 @@ import android.support.annotation.RestrictTo; import android.support.annotation.RestrictTo.Scope; import com.taobao.weex.dom.WXImageQuality; + +import java.lang.ref.WeakReference; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.HashMap; @@ -317,29 +319,7 @@ private void setRemoteSrc(Uri rewrited, int blurRadius) { this.mBlurRadius = blurRadius; final String rewritedStr = rewrited.toString(); - imageStrategy.setImageListener(new WXImageStrategy.ImageListener() { - @Override - public void onImageFinish(String url, ImageView imageView, boolean result, Map extra) { - if (getEvents().contains(Constants.Event.ONLOAD)) { - Map params = new HashMap(); - Map size = new HashMap<>(2); - if (imageView != null && imageView instanceof Measurable) { - size.put("naturalWidth", ((Measurable) imageView).getNaturalWidth()); - size.put("naturalHeight", ((Measurable) imageView).getNaturalHeight()); - } else { - size.put("naturalWidth", 0); - size.put("naturalHeight", 0); - } - - if (containsEvent(Constants.Event.ONLOAD)) { - params.put("success", result); - params.put("size", size); - fireEvent(Constants.Event.ONLOAD, params); - } - } - monitorImgSize(imageView,rewritedStr); - } - }); + imageStrategy.setImageListener(new MyImageListener(this,rewritedStr)); String placeholder=null; if(getAttrs().containsKey(Constants.Name.PLACEHOLDER)){ @@ -514,4 +494,42 @@ public interface Measurable { int getNaturalWidth(); int getNaturalHeight(); } + + public static class MyImageListener implements WXImageStrategy.ImageListener { + + private WeakReference wxImageWeakReference; + + private String rewritedStr; + + MyImageListener(WXImage image,String rewritedStr) { + this.wxImageWeakReference = new WeakReference(image); + this.rewritedStr = rewritedStr; + } + + @Override + public void onImageFinish(String url, ImageView imageView, boolean result, Map extra) { + WXImage image = wxImageWeakReference.get(); + + if(image == null) + return; + + if (image.getEvents().contains(Constants.Event.ONLOAD)) { + Map params = new HashMap(); + Map size = new HashMap<>(2); + if (imageView != null && imageView instanceof Measurable) { + size.put("naturalWidth", ((Measurable) imageView).getNaturalWidth()); + size.put("naturalHeight", ((Measurable) imageView).getNaturalHeight()); + } else { + size.put("naturalWidth", 0); + size.put("naturalHeight", 0); + } + if (image.containsEvent(Constants.Event.ONLOAD)) { + params.put("success", result); + params.put("size", size); + image.fireEvent(Constants.Event.ONLOAD, params); + } + } + image.monitorImgSize(imageView,rewritedStr); + } + } } diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/config/AutoScanConfigRegister.java b/android/sdk/src/main/java/com/taobao/weex/ui/config/AutoScanConfigRegister.java index b8b5805f88..fb0a52bc95 100644 --- a/android/sdk/src/main/java/com/taobao/weex/ui/config/AutoScanConfigRegister.java +++ b/android/sdk/src/main/java/com/taobao/weex/ui/config/AutoScanConfigRegister.java @@ -151,7 +151,7 @@ private static void doScanConfigSync(){ WXSDKEngine.registerComponent(configComponentHolder, configComponentHolder.isAppendTree(), configComponentHolder.getType()); } } - }catch (Exception e){ + }catch (Throwable e){ WXLogUtils.e(TAG, e); } } diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index aaf8be7f5c..bfbf06cf5d 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -77,8 +77,6 @@ 4532670D213FCFB400DAA620 /* WXDisplayLinkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 45326709213FC84900DAA620 /* WXDisplayLinkManager.m */; }; 453267142140E38900DAA620 /* vcomponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 453267122140E38900DAA620 /* vcomponent.h */; }; 453267152140E38900DAA620 /* vcomponent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 453267132140E38900DAA620 /* vcomponent.cc */; }; - 453267202142731000DAA620 /* binary_file.h in Headers */ = {isa = PBXBuildFile; fileRef = 4532671E2142731000DAA620 /* binary_file.h */; }; - 453267212142731000DAA620 /* binary_file.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4532671F2142731000DAA620 /* binary_file.cc */; }; 4547FD012152048700E79971 /* class_object.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4547FCFF2152048600E79971 /* class_object.cc */; }; 4547FD022152048700E79971 /* class_object.h in Headers */ = {isa = PBXBuildFile; fileRef = 4547FD002152048600E79971 /* class_object.h */; }; 4547FD032152049F00E79971 /* class_object.h in Headers */ = {isa = PBXBuildFile; fileRef = 4547FD002152048600E79971 /* class_object.h */; }; @@ -305,6 +303,19 @@ 841CD1051F974DFA0081196D /* WXExceptionUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 841CD1041F97399C0081196D /* WXExceptionUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; 841CD1061F974DFA0081196D /* WXExceptionUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 841CD1041F97399C0081196D /* WXExceptionUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; 841CD1071F974E000081196D /* WXExceptionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 841CD1021F9739890081196D /* WXExceptionUtils.m */; }; + 98399A8B21916A9800D83CCE /* exec_state_section.cc in Sources */ = {isa = PBXBuildFile; fileRef = 98399A7E21916A9600D83CCE /* exec_state_section.cc */; }; + 98399A8C21916A9800D83CCE /* exec_state_binary.cc in Sources */ = {isa = PBXBuildFile; fileRef = 98399A7F21916A9600D83CCE /* exec_state_binary.cc */; }; + 98399A8D21916A9800D83CCE /* class_regex.cc in Sources */ = {isa = PBXBuildFile; fileRef = 98399A8021916A9600D83CCE /* class_regex.cc */; }; + 98399A8E21916A9800D83CCE /* exec_state_binary.h in Headers */ = {isa = PBXBuildFile; fileRef = 98399A8121916A9600D83CCE /* exec_state_binary.h */; }; + 98399A8F21916A9800D83CCE /* class_console.cc in Sources */ = {isa = PBXBuildFile; fileRef = 98399A8221916A9700D83CCE /* class_console.cc */; }; + 98399A9021916A9800D83CCE /* class_window.cc in Sources */ = {isa = PBXBuildFile; fileRef = 98399A8321916A9700D83CCE /* class_window.cc */; }; + 98399A9121916A9800D83CCE /* class_function.cc in Sources */ = {isa = PBXBuildFile; fileRef = 98399A8421916A9700D83CCE /* class_function.cc */; }; + 98399A9221916A9800D83CCE /* class_window.h in Headers */ = {isa = PBXBuildFile; fileRef = 98399A8521916A9700D83CCE /* class_window.h */; }; + 98399A9321916A9800D83CCE /* class_console.h in Headers */ = {isa = PBXBuildFile; fileRef = 98399A8621916A9700D83CCE /* class_console.h */; }; + 98399A9421916A9800D83CCE /* class_regex.h in Headers */ = {isa = PBXBuildFile; fileRef = 98399A8721916A9700D83CCE /* class_regex.h */; }; + 98399A9521916A9800D83CCE /* exec_state_section.h in Headers */ = {isa = PBXBuildFile; fileRef = 98399A8821916A9700D83CCE /* exec_state_section.h */; }; + 98399A9621916A9800D83CCE /* class_function.h in Headers */ = {isa = PBXBuildFile; fileRef = 98399A8921916A9800D83CCE /* class_function.h */; }; + 98399A9721916A9800D83CCE /* op_code.cc in Sources */ = {isa = PBXBuildFile; fileRef = 98399A8A21916A9800D83CCE /* op_code.cc */; }; 9B9E74791FA2DB5800DAAEA9 /* WXTestBridgeMethodDummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9E74781FA2DB5800DAAEA9 /* WXTestBridgeMethodDummy.m */; }; B82A159820F8556F0098A509 /* WXSDKInstance_performance.m in Sources */ = {isa = PBXBuildFile; fileRef = 17B1221F2090AA9300387E33 /* WXSDKInstance_performance.m */; }; B82A159920F857200098A509 /* WXSDKError.m in Sources */ = {isa = PBXBuildFile; fileRef = 17B122242090AAB000387E33 /* WXSDKError.m */; }; @@ -1083,8 +1094,6 @@ 45326709213FC84900DAA620 /* WXDisplayLinkManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXDisplayLinkManager.m; sourceTree = ""; }; 453267122140E38900DAA620 /* vcomponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vcomponent.h; sourceTree = ""; }; 453267132140E38900DAA620 /* vcomponent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vcomponent.cc; sourceTree = ""; }; - 4532671E2142731000DAA620 /* binary_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = binary_file.h; sourceTree = ""; }; - 4532671F2142731000DAA620 /* binary_file.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = binary_file.cc; sourceTree = ""; }; 4547FCFF2152048600E79971 /* class_object.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = class_object.cc; sourceTree = ""; }; 4547FD002152048600E79971 /* class_object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = class_object.h; sourceTree = ""; }; 4547FD0B215392F900E79971 /* js_common_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = js_common_function.h; sourceTree = ""; }; @@ -1294,6 +1303,19 @@ 77E65A181C155F25008B8775 /* WXScrollerComponent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WXScrollerComponent.mm; sourceTree = ""; }; 841CD1021F9739890081196D /* WXExceptionUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXExceptionUtils.m; sourceTree = ""; }; 841CD1041F97399C0081196D /* WXExceptionUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXExceptionUtils.h; sourceTree = ""; }; + 98399A7E21916A9600D83CCE /* exec_state_section.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exec_state_section.cc; sourceTree = ""; }; + 98399A7F21916A9600D83CCE /* exec_state_binary.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exec_state_binary.cc; sourceTree = ""; }; + 98399A8021916A9600D83CCE /* class_regex.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = class_regex.cc; sourceTree = ""; }; + 98399A8121916A9600D83CCE /* exec_state_binary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exec_state_binary.h; sourceTree = ""; }; + 98399A8221916A9700D83CCE /* class_console.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = class_console.cc; sourceTree = ""; }; + 98399A8321916A9700D83CCE /* class_window.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = class_window.cc; sourceTree = ""; }; + 98399A8421916A9700D83CCE /* class_function.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = class_function.cc; sourceTree = ""; }; + 98399A8521916A9700D83CCE /* class_window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = class_window.h; sourceTree = ""; }; + 98399A8621916A9700D83CCE /* class_console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = class_console.h; sourceTree = ""; }; + 98399A8721916A9700D83CCE /* class_regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = class_regex.h; sourceTree = ""; }; + 98399A8821916A9700D83CCE /* exec_state_section.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exec_state_section.h; sourceTree = ""; }; + 98399A8921916A9800D83CCE /* class_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = class_function.h; sourceTree = ""; }; + 98399A8A21916A9800D83CCE /* op_code.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = op_code.cc; sourceTree = ""; }; 9B9E74771FA2DB5800DAAEA9 /* WXTestBridgeMethodDummy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXTestBridgeMethodDummy.h; sourceTree = ""; }; 9B9E74781FA2DB5800DAAEA9 /* WXTestBridgeMethodDummy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXTestBridgeMethodDummy.m; sourceTree = ""; }; B8394F3521468AF100CA1EFF /* render_action_trigger_vsync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = render_action_trigger_vsync.h; sourceTree = ""; }; @@ -2224,6 +2246,18 @@ isa = PBXGroup; children = ( B8F2C7122133A8BC00635B37 /* monitor */, + 98399A8221916A9700D83CCE /* class_console.cc */, + 98399A8621916A9700D83CCE /* class_console.h */, + 98399A8421916A9700D83CCE /* class_function.cc */, + 98399A8921916A9800D83CCE /* class_function.h */, + 98399A8021916A9600D83CCE /* class_regex.cc */, + 98399A8721916A9700D83CCE /* class_regex.h */, + 98399A8321916A9700D83CCE /* class_window.cc */, + 98399A8521916A9700D83CCE /* class_window.h */, + 98399A7F21916A9600D83CCE /* exec_state_binary.cc */, + 98399A8121916A9600D83CCE /* exec_state_binary.h */, + 98399A7E21916A9600D83CCE /* exec_state_section.cc */, + 98399A8821916A9700D83CCE /* exec_state_section.h */, B8F2C6E32133A83C00635B37 /* ast_builder.cc */, B8F2C6DB2133A83B00635B37 /* ast_builder.h */, B8A72C98213F8BAD0024E7BE /* class_json.cc */, @@ -2241,8 +2275,6 @@ B8F2C6D72133A83B00635B37 /* class.cc */, B8F2C6D22133A83A00635B37 /* class.h */, B8F2C6CE2133A83A00635B37 /* common_error.h */, - 4532671F2142731000DAA620 /* binary_file.cc */, - 4532671E2142731000DAA620 /* binary_file.h */, B8F2C6D32133A83A00635B37 /* rax_jsx_ast.cc */, B8F2C6D12133A83A00635B37 /* rax_jsx_ast.h */, B8F2C6D92133A83B00635B37 /* rax_parser_builder.cc */, @@ -2277,15 +2309,16 @@ B8D66B0A2125572F003960BD /* scanner.h */, B8D66B0C2125572F003960BD /* handle.h */, B8D66B0D2125572F003960BD /* exec_state.h */, + B8D66B182125572F003960BD /* exec_state.cc */, B8D66B0E2125572F003960BD /* object.h */, B8D66B0F2125572F003960BD /* table.h */, B8D66B112125572F003960BD /* token.h */, B8D66B122125572F003960BD /* vm.h */, B8D66B132125572F003960BD /* op_code.h */, + 98399A8A21916A9800D83CCE /* op_code.cc */, B8D66B142125572F003960BD /* ast_visitor.h */, B8D66B152125572F003960BD /* object.cc */, B8D66B162125572F003960BD /* token.cc */, - B8D66B182125572F003960BD /* exec_state.cc */, ); path = data_render; sourceTree = ""; @@ -2670,6 +2703,7 @@ 59A5961C1CB630F10012CD52 /* WXComponent+Navigation.h in Headers */, B8D66C3D21255730003960BD /* render_action_createfinish.h in Headers */, 775BEE6E1C1BD8F4008D1629 /* WXImgLoaderProtocol.h in Headers */, + 98399A8E21916A9800D83CCE /* exec_state_binary.h in Headers */, B8D66C1321255730003960BD /* core_side_in_script.h in Headers */, 7410811F1CED585A001BC6E5 /* WXComponentManager.h in Headers */, B8D66C8521255730003960BD /* render_appbar_factory.h in Headers */, @@ -2683,9 +2717,9 @@ B8D66BE12125572F003960BD /* handle.h in Headers */, B8D66BCD2125572F003960BD /* statement.h in Headers */, 77D161241C02DDD10010B15B /* WXSDKInstance.h in Headers */, - 453267202142731000DAA620 /* binary_file.h in Headers */, DC6836E61EBB12B200AD2D84 /* WXConfigCenterProtocol.h in Headers */, DC7764941F3C2CA300B5727E /* WXRecyclerDragController.h in Headers */, + 98399A9221916A9800D83CCE /* class_window.h in Headers */, 74A4BAA61CB4F98300195969 /* WXStreamModule.h in Headers */, B8D66CB321255730003960BD /* make_copyable.h in Headers */, 740451EA1E14BB26004157CB /* WXServiceFactory.h in Headers */, @@ -2729,6 +2763,7 @@ B8D66C9121255730003960BD /* render_factory_interface.h in Headers */, DCE2CF9B1F46D4220021BDC4 /* WXVoiceOverModule.h in Headers */, 74BB5FB91DFEE81A004FC3DF /* WXMetaModule.h in Headers */, + 98399A9621916A9800D83CCE /* class_function.h in Headers */, DCA0EF641D6EED6F00CB18B9 /* WXGlobalEventModule.h in Headers */, 2A837AB21CD9DE9200AEDF03 /* WXLoadingComponent.h in Headers */, B8D66BBD2125572F003960BD /* vnode_exec_env.h in Headers */, @@ -2833,6 +2868,7 @@ C43C03E81EC8ACA40044C7FF /* WXPrerenderManager.h in Headers */, 453267142140E38900DAA620 /* vcomponent.h in Headers */, 17C74F0C2072145100AB4CAB /* WXAnalyzerCenter.h in Headers */, + 98399A9321916A9800D83CCE /* class_console.h in Headers */, B8D66CD121255730003960BD /* thread_impl_darwin.h in Headers */, B8D66CBD21255730003960BD /* closure.h in Headers */, C4B834281DE69B09007AD27E /* WXPickerModule.h in Headers */, @@ -2842,6 +2878,7 @@ B8D66CDD21255730003960BD /* message_loop.h in Headers */, 742AD7301DF98C45007DC46C /* WXResourceRequestHandler.h in Headers */, 77E65A151C155EB5008B8775 /* WXTextComponent.h in Headers */, + 98399A9421916A9800D83CCE /* class_regex.h in Headers */, B8D66C9921255730003960BD /* weex_core_manager.h in Headers */, C4B3D6D41E6954300013F38D /* WXEditComponent.h in Headers */, 74CC7A1C1C2BC5F800829368 /* WXCellComponent.h in Headers */, @@ -2907,6 +2944,7 @@ D334510C1D3E19B80083598A /* WXCanvasModule.h in Headers */, 742AD73A1DF98C8B007DC46C /* WXResourceLoader.h in Headers */, 746319291C71B92600EFEBD4 /* WXModalUIModule.h in Headers */, + 98399A9521916A9800D83CCE /* exec_state_section.h in Headers */, B8D66BFF2125572F003960BD /* constants_name.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3448,6 +3486,7 @@ 2A60CE9D1C91733E00857B9F /* WXSwitchComponent.mm in Sources */, 744D61111E49979000B624B3 /* WXFooterComponent.m in Sources */, B8D66C0721255730003960BD /* core_environment.cpp in Sources */, + 98399A9021916A9800D83CCE /* class_window.cc in Sources */, 745B2D6F1E5A8E1E0092D38A /* WXRecyclerUpdateController.m in Sources */, 745B2D6B1E5A8E1E0092D38A /* WXRecyclerComponent.mm in Sources */, B8D66C0D21255730003960BD /* core_side_in_platform.cpp in Sources */, @@ -3455,7 +3494,6 @@ 2A837AB71CD9DE9200AEDF03 /* WXRefreshComponent.mm in Sources */, 74A4BA9B1CB3BAA100195969 /* WXThreadSafeMutableDictionary.m in Sources */, 77E65A1A1C155F25008B8775 /* WXScrollerComponent.mm in Sources */, - 453267212142731000DAA620 /* binary_file.cc in Sources */, 747A787D1D1BAAC900DED9D0 /* WXComponent+ViewManagement.mm in Sources */, C4E375371E5FCBD3009B2D9C /* WXComponent+BoxShadow.m in Sources */, C43C03E91EC8ACA40044C7FF /* WXPrerenderManager.m in Sources */, @@ -3466,6 +3504,7 @@ B8D66C4B21255730003960BD /* render_action_remove_event.cpp in Sources */, B8F2C6F22133A83C00635B37 /* class_factory.cc in Sources */, B8D66BD32125572F003960BD /* vm.cc in Sources */, + 98399A9121916A9800D83CCE /* class_function.cc in Sources */, 2A837AB51CD9DE9200AEDF03 /* WXLoadingIndicator.m in Sources */, B8D66BBF2125572F003960BD /* vnode_render_manager.cc in Sources */, B8D66C6321255730003960BD /* render_text.cpp in Sources */, @@ -3537,6 +3576,7 @@ B8D66C8321255730003960BD /* render_creator.cpp in Sources */, 74A4BAA71CB4F98300195969 /* WXStreamModule.m in Sources */, 744D610D1E49978200B624B3 /* WXHeaderComponent.mm in Sources */, + 98399A8B21916A9800D83CCE /* exec_state_section.cc in Sources */, B8F2C7062133A83C00635B37 /* rax_parser_scope.cc in Sources */, 77E659F21C0C3612008B8775 /* WXModuleFactory.m in Sources */, B8D66C5F21255730003960BD /* render_action_render_success.cpp in Sources */, @@ -3565,6 +3605,7 @@ 59A596251CB6311F0012CD52 /* WXStorageModule.m in Sources */, 2AFEB17C1C747139000507FA /* WXInstanceWrap.m in Sources */, 74A4BA5C1CABBBD000195969 /* WXDebugTool.m in Sources */, + 98399A9721916A9800D83CCE /* op_code.cc in Sources */, 742AD73B1DF98C8B007DC46C /* WXResourceLoader.m in Sources */, B8A72CA0213F8BAE0024E7BE /* class_string.cc in Sources */, B8D66C6721255730003960BD /* render_scroller.cpp in Sources */, @@ -3574,6 +3615,7 @@ D334510D1D3E19B80083598A /* WXCanvasModule.m in Sources */, B8D66C1D21255730003960BD /* style.cpp in Sources */, B89543F520EB18B5006EAD63 /* WXJSCoreBridge.mm in Sources */, + 98399A8C21916A9800D83CCE /* exec_state_binary.cc in Sources */, 741081241CED6756001BC6E5 /* WXComponentFactory.m in Sources */, D362F9501C83EDA20003F546 /* WXWebViewModule.m in Sources */, 745B2D711E5A8E1E0092D38A /* WXSectionDataController.m in Sources */, @@ -3593,6 +3635,7 @@ 74CFDD3A1F45939C007A1A66 /* WXRecycleListComponent.mm in Sources */, 741DFE031DDD7D18009B020F /* WXRoundedRect.mm in Sources */, 59A596301CB632050012CD52 /* WXBaseViewController.m in Sources */, + 98399A8D21916A9800D83CCE /* class_regex.cc in Sources */, 74CC7A211C2BF9DC00829368 /* WXListComponent.mm in Sources */, 7423899C1C3174EB00D748CA /* WXWeakObjectWrapper.m in Sources */, 744BEA561D05178F00452B5D /* WXComponent+Display.m in Sources */, @@ -3619,6 +3662,7 @@ 746B923C1F46BE36009AE86B /* WXCellSlotComponent.mm in Sources */, 7463192A1C71B92600EFEBD4 /* WXModalUIModule.m in Sources */, 77D161501C02E3880010B15B /* WXUtility.m in Sources */, + 98399A8F21916A9800D83CCE /* class_console.cc in Sources */, B8F2C6F42133A83C00635B37 /* rax_parser_statistics.cc in Sources */, 1771795721416DF0006F39A9 /* WXApmForInstance.m in Sources */, 74A4BA9F1CB3C0A100195969 /* WXHandlerFactory.m in Sources */, diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m index 993e7913f8..5920dd86e8 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m @@ -1128,7 +1128,7 @@ + (void)mountContextEnvironment:(JSContext*)context }; } -+ (void)handleConsoleOutputWithArgument:(NSArray*)arguments logLevel:(WXLogFlag)logLevel ++ (void)handleConsoleOutputWithArgument:(NSArray *)arguments logLevel:(WXLogFlag)logLevel { NSMutableString *string = [NSMutableString string]; [string appendString:@"jsLog: "]; diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm index 793601e5eb..a332abf76d 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm @@ -28,6 +28,8 @@ #import "WXUtility.h" #import "WXAssert.h" #import "WXAppConfiguration.h" +#import "WXSDKEngine.h" +#import "WXAppMonitorProtocol.h" #include "base/CoreConstants.h" #include "core/manager/weex_core_manager.h" @@ -158,6 +160,32 @@ static id TO_OBJECT(NSString* s) return result; } + static void consoleWithArguments(NSArray *arguments, WXLogFlag logLevel) + { + NSMutableString *jsLog = [NSMutableString string]; + [jsLog appendString:@"jsLog: "]; + [arguments enumerateObjectsUsingBlock:^(NSString *jsVal, NSUInteger idx, BOOL *stop) { + if (idx == arguments.count - 1) { + if (logLevel) { + if (WXLogFlagWarning == logLevel) { + id appMonitorHandler = [WXSDKEngine handlerForProtocol:@protocol(WXAppMonitorProtocol)]; + if ([appMonitorHandler respondsToSelector:@selector(commitAppMonitorAlarm:monitorPoint:success:errorCode:errorMsg:arg:)]) { + [appMonitorHandler commitAppMonitorAlarm:@"weex" monitorPoint:@"jswarning" success:FALSE errorCode:@"99999" errorMsg:jsLog arg:[WXSDKEngine topInstance].pageName]; + } + } + WX_LOG(logLevel, @"%@", jsLog); + } + else { + [jsLog appendFormat:@"%@ ", jsVal] ; + WXLogInfo(@"%@", jsLog); + } + } + else { + [jsLog appendFormat:@"%@ ", jsVal]; + } + }]; + } + static void MergeBorderWidthValues(NSMutableDictionary* dict, const WXCoreBorderWidth & borders, bool isUpdate, float pixelScaleFactor) @@ -223,9 +251,7 @@ static void MergeBorderWidthValues(NSMutableDictionary* dict, assert(false); } - std::unique_ptr IOSSide::CallNativeModule(const char *page_id, const char *module, const char *method, - const char *args, int argc, - const char *options, int optionsLength) + std::unique_ptr IOSSide::CallNativeModule(const char *page_id, const char *module, const char *method, const char *args, int args_length, const char *options, int options_length) { // should not enter this function do { @@ -237,10 +263,11 @@ static void MergeBorderWidthValues(NSMutableDictionary* dict, NSString *moduleName = [NSString stringWithUTF8String:module]; NSString *methodName = [NSString stringWithUTF8String:method]; NSArray *newArguments; - if (argc > 0 && args) { + if (args && args_length > 0) { NSString *arguments = [NSString stringWithUTF8String:args]; newArguments = [WXUtility objectFromJSON:arguments]; } + LOGD("CallNativeModule:[%s]:[%s]=>%s \n", module, method, args); WXModuleMethod *method = [[WXModuleMethod alloc] initWithModuleName:moduleName methodName:methodName arguments:newArguments options:nil instance:instance]; [method invoke]; @@ -262,11 +289,35 @@ static void MergeBorderWidthValues(NSMutableDictionary* dict, // should not enter this function assert(false); } - - void IOSSide::NativeLog(const char* str_array) + + void IOSSide::NativeLog(const char *args) { // should not enter this function - assert(false); + do { + if (!args) { + break; + } + NSArray *newArguments; + if (args) { + NSString *arguments = [NSString stringWithUTF8String:args]; + newArguments = [WXUtility objectFromJSON:arguments]; + } + if (![newArguments isKindOfClass:[NSArray class]] || !newArguments.count) { + break; + } + static NSDictionary *levelMap; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + levelMap = @{@"__ERROR": @(WXLogFlagError), + @"__WARN": @(WXLogFlagWarning), + @"__INFO": @(WXLogFlagInfo), + @"__DEBUG": @(WXLogFlagDebug), + @"__LOG": @(WXLogFlagLog)}; + }); + NSString *levelStr = [newArguments lastObject]; + consoleWithArguments(newArguments, (WXLogFlag)[levelMap[levelStr] integerValue]); + + } while (0); } void IOSSide::TriggerVSync(const char* page_id) @@ -835,19 +886,7 @@ + (void)createDataRenderInstance:(NSString *)pageId contents:(NSData *)contents auto node_manager = weex::core::data_render::VNodeRenderManager::GetInstance(); NSString *optionsString = [WXUtility JSONString:options]; NSString *dataString = [WXUtility JSONString:data]; - -// NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; -// NSString *txtPath = [documentsPath stringByAppendingPathComponent:@"test.wasm"]; -// std::string path = [txtPath UTF8String]; -// std::ifstream fin(path, std::ios::in|std::ios::binary|std::ios::ate); -// unsigned length = static_cast(fin.tellg()); -// -// char* buffer = new char[length]; -// fin.seekg (0, std::ios::beg); -// fin.read(buffer, length); -// fin.close(); - - node_manager->CreatePage(static_cast(contents.bytes), contents.length, [pageId UTF8String], [optionsString UTF8String], dataString ? [dataString UTF8String] : ""); + node_manager->CreatePage(static_cast(contents.bytes), contents.length, [pageId UTF8String], [optionsString UTF8String], dataString ? [dataString UTF8String] : ""); } + (void)destroyDataRenderInstance:(NSString *)pageId diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index 87bc32650b..8cf079e158 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -53,6 +53,8 @@ #import "WXPageEventNotifyEvent.h" #import "WXCoreBridge.h" +#define WEEX_LITE_URL_SUFFIX @"wlasm" + NSString *const bundleUrlOptionKey = @"bundleUrl"; NSTimeInterval JSLibInitTime = 0; @@ -233,7 +235,9 @@ - (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data WXLogError(@"Url must be passed if you use renderWithURL"); return; } - + if ([url.absoluteString hasSuffix:WEEX_LITE_URL_SUFFIX]) { + _defaultDataRender = YES; + } _scriptURL = url; [self _checkPageName]; [self.apmInstance startRecord:self.instanceId]; @@ -257,16 +261,16 @@ - (void)renderView:(id)source options:(NSDictionary *)options data:(id)data [self _renderWithMainBundleString:source]; [WXTracingManager setBundleJSType:source instanceId:self.instanceId]; } else if ([source isKindOfClass:[NSData class]]) { - [self _renderWithOpcode:source]; + [self _renderWithData:source]; } } -- (NSString*) bundleTemplate +- (NSString *) bundleTemplate { return self.mainBundleString; } -- (void)_renderWithOpcode:(NSData *)contents +- (void)_renderWithData:(NSData *)contents { if (!self.instanceId) { WXLogError(@"Fail to find instance!"); @@ -538,8 +542,8 @@ - (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *) return; } - if ([options[@"DATA_RENDER"] boolValue] && [options[@"RENDER_WITH_BINARY"] boolValue]) { - [strongSelf _renderWithOpcode:data]; + if (strongSelf.dataRender) { + [strongSelf _renderWithData:data]; return; } @@ -775,7 +779,7 @@ - (CGFloat)pixelScaleFactor - (BOOL)dataRender { - if ([_options[@"DATA_RENDER"] boolValue]) { + if ([_options[@"WLASM_RENDER"] boolValue]) { return YES; } return _defaultDataRender; diff --git a/weex_core/Source/CMakeLists.txt b/weex_core/Source/CMakeLists.txt index 8b9df20db5..7246b9e7a4 100644 --- a/weex_core/Source/CMakeLists.txt +++ b/weex_core/Source/CMakeLists.txt @@ -73,7 +73,12 @@ set(COMMON_SRCS ./core/data_render/class_array.cc ./core/data_render/class_json.cc ./core/data_render/class_string.cc + ./core/data_render/class_regex.cc + ./core/data_render/class_console.cc + ./core/data_render/class_window.cc + ./core/data_render/class_math.cc ./core/data_render/class_factory.cc + ./core/data_render/class_function.cc ./core/data_render/class_object.cc ./core/data_render/code_generator.cc ./core/data_render/exec_state.cc @@ -92,8 +97,10 @@ set(COMMON_SRCS ./core/data_render/table.cc ./core/data_render/token.cc ./core/data_render/tokenizer.cc + ./core/data_render/op_code.cc ./core/data_render/vm.cc - ./core/data_render/binary_file.cc + ./core/data_render/exec_state_binary.cc + ./core/data_render/exec_state_section.cc ./core/data_render/vnode/vnode.cc ./core/data_render/vnode/vcomponent.cc ./core/data_render/vnode/vnode_exec_env.cc diff --git a/weex_core/Source/base/LogDefines.h b/weex_core/Source/base/LogDefines.h index d1f78d80b6..2cfac7b47b 100644 --- a/weex_core/Source/base/LogDefines.h +++ b/weex_core/Source/base/LogDefines.h @@ -62,6 +62,8 @@ #else +#define LOGE(...) ((void) 0) +#define LOGA(...) ((void) 0) #define LOGV(...) ((void) 0) #define LOGD(...) ((void) 0) #define LOGI(...) ((void) 0) diff --git a/weex_core/Source/base/ViewUtils.h b/weex_core/Source/base/ViewUtils.h index ec8866c24c..890e032ed6 100644 --- a/weex_core/Source/base/ViewUtils.h +++ b/weex_core/Source/base/ViewUtils.h @@ -19,6 +19,8 @@ #ifndef WEEX_PROJECT_VIEWUTILS_H #define WEEX_PROJECT_VIEWUTILS_H +#include +#include #include #include #include diff --git a/weex_core/Source/base/string_util.h b/weex_core/Source/base/string_util.h index 7995924982..9e07c97c6d 100644 --- a/weex_core/Source/base/string_util.h +++ b/weex_core/Source/base/string_util.h @@ -21,11 +21,11 @@ #define CORE_BASE_STRING_UTIL_H #include -#include +#include #ifdef OS_ANDROID #include #else -#include +#include #endif #include "base/third_party/icu/icu_utf.h" diff --git a/weex_core/Source/base/thread/thread_impl_darwin.cc b/weex_core/Source/base/thread/thread_impl_darwin.cc index a45d80a52f..c53ea4bdaf 100644 --- a/weex_core/Source/base/thread/thread_impl_darwin.cc +++ b/weex_core/Source/base/thread/thread_impl_darwin.cc @@ -29,7 +29,12 @@ ThreadImplDarwin::~ThreadImplDarwin() {} void ThreadImplDarwin::SetName(const std::string& name) { ThreadImpl::SetName(name); - pthread_setname_np(name.c_str()); +#ifdef OS_LINUX + pthread_setname_np(pthread_self(), name.c_str()); +#else + pthread_setname_np(name.c_str()); +#endif + } } // namespace base diff --git a/weex_core/Source/core/config/core_environment.cpp b/weex_core/Source/core/config/core_environment.cpp index 626145d0a4..63eea5f41e 100644 --- a/weex_core/Source/core/config/core_environment.cpp +++ b/weex_core/Source/core/config/core_environment.cpp @@ -16,9 +16,11 @@ * specific language governing permissions and limitations * under the License. */ + +#include +#include #include "core_environment.h" #include "base/CoreConstants.h" -#include #include #include "base/LogDefines.h" diff --git a/weex_core/Source/core/css/css_value_getter.cpp b/weex_core/Source/core/css/css_value_getter.cpp index ea78c96e01..f576245e32 100644 --- a/weex_core/Source/core/css/css_value_getter.cpp +++ b/weex_core/Source/core/css/css_value_getter.cpp @@ -16,6 +16,8 @@ * specific language governing permissions and limitations * under the License. */ + +#include #include "css_value_getter.h" #include "constants_value.h" #include "constants_name.h" diff --git a/weex_core/Source/core/data_render/ast.h b/weex_core/Source/core/data_render/ast.h index d382a4ea8e..1bdfa7ff64 100644 --- a/weex_core/Source/core/data_render/ast.h +++ b/weex_core/Source/core/data_render/ast.h @@ -67,10 +67,14 @@ namespace data_render { M(ForStatement) \ M(ContinueStatement) \ M(BreakStatement) \ + M(CaseStatement) \ + M(SwitchStatement) \ + M(TryCatchStatement) \ M(BlockStatement) \ M(FunctionPrototype) \ M(FunctionStatement) \ M(StringConstant) \ + M(RegexConstant) \ M(BinaryExpression) \ M(TernaryExpression) \ M(AssignExpression) \ @@ -99,6 +103,7 @@ namespace data_render { M(NewExpression) \ M(ArrowFunctionStatement) \ M(ClassBody) \ + M(ClassProperty) \ M(ExpressionList) class ASTVisitor; @@ -117,7 +122,7 @@ enum class ASTNodeType { kNrType }; -extern const char* type_as_string[(int)ASTNodeType::kNrType]; +extern const char *type_as_string[(int)ASTNodeType::kNrType]; class Expression : public RefCountObject { protected: @@ -132,7 +137,7 @@ class Expression : public RefCountObject { virtual ASTNodeType type() const = 0; virtual void SetScope(Scope *scope) { scope_ = scope; } virtual Scope *GetScope() { return scope_; } - + // helper conversion functions #define AS_EXPRESSION_FUNCTION(Type) \ virtual Handle As##Type() { assert(0 && "Expression is not " #Type); } @@ -174,17 +179,17 @@ class ExpressionList : public Expression { private: std::vector> exprs_; }; - + class ClassBody : public Expression { public: using iterator = std::vector>::iterator; - + void Insert(Handle expr) { body_.push_back(expr); } - + size_t Size() { return body_.size(); } - + std::vector>& raw_list() { return body_; } - + iterator begin() { return body_.begin(); } iterator end() { return body_.end(); } DEFINE_NODE_TYPE(ClassBody, Expression); @@ -235,6 +240,38 @@ class StringConstant : public Expression { DEFINE_NODE_TYPE(StringConstant, Expression); }; +class RegexConstant : public Expression { + private: + std::string str_; + std::string str_flag_; + + public: + RegexConstant(Position &loc, Scope *scope, const std::string &str) + : Expression(loc, scope) + { + auto p = str.find_last_of('$'); + if (p==std::string::npos){ + str_ = str; + } else { + str_ = str.substr(0,p); + str_flag_ = str.substr(p+1); + } + } + RegexConstant(const std::string& str) + : Expression() { + auto p = str.find_last_of('$'); + if (p==std::string::npos){ + str_ = str; + } else { + str_ = str.substr(0,p); + str_flag_ = str.substr(p+1); + } + } + std::string& reg() { return str_; } + std::string& flag() { return str_flag_; } + DEFINE_NODE_TYPE(RegexConstant, Expression); +}; + class TernaryExpression : public Expression { public: TernaryExpression(Position &loc, Scope *scope, Handle first, @@ -305,7 +342,7 @@ class BinaryExpression : public Expression { Handle lhs_; Handle rhs_; }; - + enum class DeclarationKind { kConst, }; @@ -462,7 +499,8 @@ enum class PrefixOperation { kIncrement, kDecrement, kNot, - kUnfold + kUnfold, + kTypeof, }; class PrefixExpression : public Expression { @@ -497,7 +535,7 @@ class PostfixExpression : public Expression { PostfixOperation op_; Handle expr_; }; - + enum class ProxyOrder { ProxyArray, ProxyObject }; class ObjectConstant : public Expression { @@ -538,7 +576,7 @@ class ArrayConstant : public Expression { private: ProxyArray exprs_; }; - + enum class AssignOperation { kAssign, kAssignAdd, @@ -567,37 +605,36 @@ class UndefinedConstant : public Expression { UndefinedConstant(Position &loc, Scope *scope) : Expression(loc, scope) { } - + DEFINE_NODE_TYPE(UndefinedConstant, Expression); }; - + class NewExpression : public Expression { public: - NewExpression(Position &loc, Scope *scope, Handle member) - : Expression(loc, scope), member_{ member } { } - NewExpression(Handle member) - : Expression(), member_{ member } { } + NewExpression(Position &loc, Scope *scope, Handle name, Handle args = nullptr) + : Expression(loc, scope), name_(name), args_(args) { } + NewExpression(Handle name, Handle args = nullptr) + : Expression(), name_(name), args_(args) { } - Handle member() { return member_; } + Handle name() { return name_; } + Handle args() { return args_; } bool ProduceRValue() override { return false; } - void set_is_class_(bool is_class) { is_class_ = is_class; }; - bool is_class() { return is_class_; } DEFINE_NODE_TYPE(NewExpression, Expression); private: - Handle member_; - bool is_class_{false}; + Handle name_; + Handle args_; }; - + class ThisExpression : public Expression { public: ThisExpression(Position &loc, Scope *scope) : Expression(loc, scope) { } - + bool ProduceRValue() override { return false; } DEFINE_NODE_TYPE(ThisExpression, Expression); }; - + class CommaExpression : public Expression { public: CommaExpression(Handle exprs) @@ -605,13 +642,50 @@ class CommaExpression : public Expression { CommaExpression(Position &loc, Scope *scope, Handle exprs) : Expression(loc, scope), exprs_{ exprs } { } - + Handle exprs() { return exprs_; } DEFINE_NODE_TYPE(CommaExpression, Expression); private: Handle exprs_; }; +class ClassProperty : public Expression { +public: + ClassProperty(Position &loc, Scope *scope, std::string name, Handle init) + : Expression(loc, scope), name_(name), init_{init} { } + inline void set_is_static(bool is_static) { is_static_ = is_static; } + inline bool is_static() { return is_static_; } + inline std::string &name() { return name_; } + inline Handle& init() { return init_; } + DEFINE_NODE_TYPE(ClassProperty, Expression); +private: + std::string name_; + Handle init_; + bool is_static_{false}; +}; + +class TryCatchStatement : public Expression { + public: + TryCatchStatement(Handle try_block, + Handle catch_expr, Handle catch_block, Handle finally) + : Expression(), try_block_{ try_block }, catch_expr_{ catch_expr }, + catch_block_{ catch_block }, finally_{ finally } + { } + + + Handle try_block() { return try_block_; } + Handle catch_expr() { return catch_expr_; } + Handle catch_block() { return catch_block_; } + Handle finally() { return finally_; } + DEFINE_NODE_TYPE(TryCatchStatement,Expression); + private: + Handle try_block_; + Handle catch_expr_; + Handle catch_block_; + Handle finally_; +}; + + } // namespace data_render } // namespace core } // namespace weex diff --git a/weex_core/Source/core/data_render/ast_builder.cc b/weex_core/Source/core/data_render/ast_builder.cc index a40cc05341..b3d62dce55 100644 --- a/weex_core/Source/core/data_render/ast_builder.cc +++ b/weex_core/Source/core/data_render/ast_builder.cc @@ -106,10 +106,10 @@ Handle ASTBuilder::NewPrefixExpression(PrefixOperation op, HandleNewPrefixExpression(locator()->location(), manager()->current(), op, expr)); } -Handle ASTBuilder::NewNewExpression(Handle expr) +Handle ASTBuilder::NewNewExpression(Handle expr, Handle args) { COUNT(); - return save(factory()->NewNewExpression(locator()->location(), manager()->current(), expr)); + return save(factory()->NewNewExpression(locator()->location(), manager()->current(), expr, args)); } Handle ASTBuilder::NewPostfixExpression(PostfixOperation op, @@ -166,6 +166,12 @@ Handle ASTBuilder::NewStringConstant(const std::string &str) COUNT(); return save(factory()->NewStringConstant(locator()->location(), manager()->current(), str)); } + +Handle ASTBuilder::NewRegexConstant(const std::string &str) +{ + COUNT(); + return save(factory()->NewRegexConstant(locator()->location(), manager()->current(), str)); +} Handle ASTBuilder::NewThisExpression() { @@ -261,6 +267,29 @@ Handle ASTBuilder::NewClassStatement(Handle identifier, return save(factory()->NewClassStatement(locator()->location(), manager()->current(), identifier, superClass, body)); } +Handle ASTBuilder::NewClassProperty(std::string name, Handle init) { + COUNT(); + return save(factory()->NewClassProperty(locator()->location(), manager()->current(), name, init)); +} + +Handle ASTBuilder::NewCaseStatement(Handle test_case,Handle expr) { + COUNT(); + return save(factory()->NewCaseStatement(locator()->location(), manager()->current(), test_case, expr)); +} + +Handle ASTBuilder::NewSwitchStatement(Handle test_value, + std::vector> cases) { + COUNT(); + return save(factory()->NewSwitchStatement(locator()->location(), manager()->current(), test_value, cases)); +} +Handle ASTBuilder::NewTryCatchStatement(Handle try_block, + Handle catch_expr, + Handle catch_block, + Handle finally) { + COUNT(); + return save(factory()->NewTryCatchStatement(locator()->location(), manager()->current(),try_block,catch_expr,catch_block,finally)); +} + } } } diff --git a/weex_core/Source/core/data_render/ast_builder.h b/weex_core/Source/core/data_render/ast_builder.h index 77d331a6c0..d72961a90f 100644 --- a/weex_core/Source/core/data_render/ast_builder.h +++ b/weex_core/Source/core/data_render/ast_builder.h @@ -33,7 +33,7 @@ namespace weex { namespace core { namespace data_render { - + class ASTBuilder { public: ASTBuilder(ParserContext *ctx, ASTFactory *factory, @@ -51,7 +51,7 @@ class ASTBuilder { // create a new node representing JavaScript ternary expression Handle NewTernaryExpression(Handle first, Handle second, Handle third); // create a new node representing JavaScript binary expression - Handle NewBinaryExpression(BinaryOperation op, Handle lhs, Handle rhs); + Handle NewBinaryExpression(BinaryOperation op, Handle lhs, Handle rhs); // create a new node representing JavaScript assign expression Handle NewAssignExpression(Handle lhs, Handle rhs); Handle NewDeclaration(std::string name, Handle init = nullptr); @@ -63,7 +63,7 @@ class ASTBuilder { // create a new node representing JavaScript postfix operation Handle NewPostfixExpression(PostfixOperation op, Handle expr); // create a new node representing JavaScript `new` expression - Handle NewNewExpression(Handle expr); + Handle NewNewExpression(Handle expr, Handle args = nullptr); // create a new node representing JavaScript Identifier Handle NewIdentifier(std::string name); // create a new node representing JavaScript argument list @@ -80,6 +80,8 @@ class ASTBuilder { Handle NewNullConstant(); // create a new node representing JavaScript string Handle NewStringConstant(const std::string &str); + + Handle NewRegexConstant(const std::string &str); // create a new node representing JavaScript boolean Handle NewBooleanConstant(bool value); // create a new node representing JavaScript 'this' @@ -105,19 +107,25 @@ class ASTBuilder { // create a new node representing JavaScript for loop Handle NewForStatement(ForKind kind, Handle init, Handle cond, Handle update, Handle body); // create a new node representing JavaScript break statement + Handle NewCaseStatement(Handle test_case,Handle expr); + Handle NewSwitchStatement(Handle test_value,std::vector> cases); + Handle NewTryCatchStatement(Handle try_block, + Handle catch_expr, Handle catch_block, Handle finally); Handle NewBreakStatement(Handle label = nullptr); - + // create a new node representing JavaScript continue statement Handle NewContinueStatement(Handle label = nullptr); Handle NewArrowFunctionStatement(Handle body, std::vector> args); Handle NewJSXNodeExpression(Handle identifier, Handle props, Handle parent, std::vector> childrens); Handle NewClassStatement(Handle identifier, Handle superClass, Handle body); + Handle NewClassProperty(std::string name, Handle init = nullptr); + Handle NewClassBody(); ASTFactory *factory() { return factory_; } SourceLocator *locator() { return locator_; } ScopeManager *manager() { return manager_; } - + template inline Handle save(Handle handle) { exprs_.push_back(handle); diff --git a/weex_core/Source/core/data_render/ast_factory.cc b/weex_core/Source/core/data_render/ast_factory.cc index a1742ee4d9..3f87e78ba4 100644 --- a/weex_core/Source/core/data_render/ast_factory.cc +++ b/weex_core/Source/core/data_render/ast_factory.cc @@ -38,23 +38,23 @@ ASTFactory* ASTFactory::GetFactoryInstance() { Handle ASTFactory::NewExpressionList() { return MakeHandle(); } - + Handle ASTFactory::NewExpressionList(const std::vector>& list) { return MakeHandle(list); } - + Handle ASTFactory::NewClassBody() { return MakeHandle(); } - + Handle ASTFactory::NewThisExpression() { return MakeHandle(); } - -Handle ASTFactory::NewNewExpression(Handle expr) { - return MakeHandle(expr); + +Handle ASTFactory::NewNewExpression(Handle expr, Handle args) { + return MakeHandle(expr, args); } - + Handle ASTFactory::NewIdentifier(std::string name) { return MakeHandle(name); } @@ -88,7 +88,7 @@ Handle ASTFactory::NewFunctionPrototype(std::string name, std::vecto Handle ASTFactory::NewFunctionStatement(Handle proto, Handle body) { return MakeHandle(proto, body); } - + Handle ASTFactory::NewReturnStatement(Handle expr) { return MakeHandle(expr); } @@ -96,7 +96,7 @@ Handle ASTFactory::NewReturnStatement(Handle expr) { Handle ASTFactory::NewDeclaration(std::string name, Handle init) { return MakeHandle(name, init); } - + Handle ASTFactory::NewDeclarationList() { return MakeHandle(); } @@ -108,7 +108,7 @@ Handle ASTFactory::NewDeclarationList(std::vector ASTFactory::NewCommaExpression(const std::vector>& list) { return MakeHandle(NewExpressionList(list)); } - + Handle ASTFactory::NewBinaryExpression(BinaryOperation op, Handle lhs, Handle rhs) { return MakeHandle(op, lhs, rhs); } @@ -132,7 +132,7 @@ Handle ASTFactory::NewNullConstant() { Handle ASTFactory::NewCallExpression(MemberAccessKind kind, Handle expr, Handle member, std::vector> args) { return MakeHandle(kind, expr, member, args); } - + Handle ASTFactory::NewCallExpression(Handle func, std::vector> args) { return MakeHandle(func, args); } @@ -153,11 +153,11 @@ Handle ASTFactory::NewForStatement(ForKind kind, Handle Handle update, Handle body) { return MakeHandle(kind, init, condition, update, body); } - + Handle ASTFactory::NewObjectConstant(ProxyObject obj) { return MakeHandle(std::move(obj)); } - + Handle ASTFactory::NewAssignExpression(Handle lhs, Handle rhs) { return MakeHandle(lhs, rhs); } @@ -165,7 +165,7 @@ Handle ASTFactory::NewAssignExpression(Handle lhs, Handl Handle ASTFactory::NewIfStatement(Handle condition, Handle then) { return MakeHandle(condition, then); } - + Handle ASTFactory::NewIfElseStatement(Handle condition, Handle then, Handle els) { return MakeHandle(condition, then, els); @@ -193,7 +193,7 @@ Handle ASTFactory::NewAssignExpression(Position &loc, Scope *scope, { return MakeHandle(loc, scope, lhs, rhs); } - + Handle ASTFactory::NewPrefixExpression(Position &loc, Scope *scope, PrefixOperation op, Handle expr) { @@ -205,7 +205,7 @@ Handle ASTFactory::NewPostfixExpression(Position &loc, Scope *scope, { return MakeHandle(loc, scope, op, expr); } - + Handle ASTFactory::NewIntegralConstant(Position &loc, Scope *scope, int value) { return MakeHandle(loc, scope, value); @@ -214,17 +214,17 @@ Handle ASTFactory::NewDoubleConstant(Position &loc, Scope *scope, do { return MakeHandle(loc, scope, value); } - -Handle ASTFactory::NewNewExpression(Position &loc, Scope *scope, Handle expr) + +Handle ASTFactory::NewNewExpression(Position &loc, Scope *scope, Handle expr, Handle args) { - return MakeHandle(loc, scope, expr); + return MakeHandle(loc, scope, expr, args); } - + Handle ASTFactory::NewIdentifier(Position &loc, Scope *scope, std::string name) { return MakeHandle(loc, scope, name); } - + Handle ASTFactory::NewArgumentList(Position &loc, Scope *scope, Handle args) { return MakeHandle(loc, scope, std::move(args)); @@ -234,31 +234,36 @@ Handle ASTFactory::NewCallExpression(Position &loc, Scope *scope, Me { return MakeHandle(loc, scope, kind, func, args); } - + Handle ASTFactory::NewCallExpression(Position &loc, Scope *scope, Handlefunc, Handle args) { return MakeHandle(loc, scope, func, args); } - + Handle ASTFactory::NewNullConstant(Position &loc, Scope *scope) { return MakeHandle(loc, scope); } - + Handle ASTFactory::NewStringConstant(Position &loc, Scope *scope, std::string str) { return MakeHandle(loc, scope, str); } - + +Handle ASTFactory::NewRegexConstant(Position &loc, Scope *scope, std::string str) +{ + return MakeHandle(loc, scope, str); +} + Handle ASTFactory::NewBooleanConstant(Position &loc, Scope *scope, bool val) { return MakeHandle(loc, scope, val); } - + Handle ASTFactory::NewThisExpression(Position &loc, Scope *scope) { return MakeHandle(loc, scope); } - + Handle ASTFactory::NewArrayConstant(Position &loc, Scope *scope, ProxyArray arr) { return MakeHandle(loc, scope, std::move(arr)); @@ -269,17 +274,17 @@ Handle ASTFactory::NewObjectConstant(Position &loc, Scope *scope, { return MakeHandle(loc, scope, std::move(obj)); } - + Handle ASTFactory::NewFunctionPrototype(Position &loc, Scope *scope, std::string name, std::vector args) { return MakeHandle(loc, scope, name, std::move(args)); } - + Handle ASTFactory::NewFunctionStatement(Position &loc, Scope *scope, Handle proto, Handle body) { return MakeHandle(loc, scope, proto, body); } - + Handle ASTFactory::NewBlockStatement(Position &loc, Scope *scope, Handle list) { return MakeHandle(loc, scope, list); @@ -289,7 +294,7 @@ Handle ASTFactory::NewForStatement(Position &loc, Scope *scope, ForK { return MakeHandle(loc, scope, kind, init, condition, update, body); } - + Handle ASTFactory::NewBreakStatement(Position &loc, Scope *scope, Handle label) { return MakeHandle(loc, scope, label); @@ -299,7 +304,7 @@ Handle ASTFactory::NewContinueStatement(Position &loc, Scope *scope, { return MakeHandle(loc, scope, label); } - + Handle ASTFactory::NewIfStatement(Position &loc, Scope *scope, Handle condition, Handle then) { return MakeHandle(loc, scope, condition, then); @@ -314,50 +319,77 @@ Handle ASTFactory::NewReturnStatement(Position &loc, Scope *scope, H { return MakeHandle(loc, scope, expr); } - + Handle ASTFactory::NewMemberExpression(Position &loc, Scope *scope, MemberAccessKind kind, Handle expr, Handle mem) { return MakeHandle(loc, scope, kind, expr, mem); } - + Handle ASTFactory::NewCommaExpression(Position &loc, Scope *scope, Handle l) { return MakeHandle(loc, scope, l); } - + Handle ASTFactory::NewBinaryExpression(Position &loc, Scope *scope, BinaryOperation op, Handle lhs, Handle rhs) { return MakeHandle(loc, scope, op, lhs, rhs); } - + Handle ASTFactory::NewDeclaration(Position &loc, Scope *scope, std::string name, Handle init) { return MakeHandle(loc, scope, name, init); } - + Handle ASTFactory::NewDeclaration(Position &loc, Scope *scope, Handle expr, Handle init) { return MakeHandle(loc, scope, expr, init); } - + Handle ASTFactory::NewDeclarationList(Position &loc, Scope *scope, std::vector> decls) { return MakeHandle(loc, scope, std::move(decls)); } - + Handle ASTFactory::NewArrowFunctionStatement(Position &loc, Scope *scope, Handle body, std::vector> args) { return MakeHandle(loc, scope, body, std::move(args)); } - + Handle ASTFactory::NewJSXNodeExpression(Position &loc, Scope *scope, Handle identifier, Handle props, Handle parent, std::vector> childrens) { return MakeHandle(loc, scope, identifier, props, parent, std::move(childrens)); } - + Handle ASTFactory::NewClassStatement(Position &loc, Scope *scope, Handle identifier, Handle superClass, Handle body) { return MakeHandle(loc, scope, identifier, superClass, body); } - + +Handle ASTFactory::NewCaseStatement(Position& loc, + Scope* scope, + Handle test_value,Handle expr) { + return MakeHandle(test_value,expr); +} + +Handle ASTFactory::NewSwitchStatement(Position& loc, + Scope* scope, + Handle test_case, + std::vector> cases) { + return MakeHandle(test_case,cases); +} + +Handle ASTFactory::NewClassProperty(Position &loc, Scope *scope, std::string name, Handle init) +{ + return MakeHandle(loc, scope, name, init); +} + +Handle ASTFactory::NewTryCatchStatement(Position& loc, + Scope* scope, + Handle try_block, + Handle catch_expr, + Handle catch_block, + Handle finally) { + return MakeHandle(try_block,catch_expr,catch_block,finally); +} + } // namespace data_render } // namespace core } // namespace weex diff --git a/weex_core/Source/core/data_render/ast_factory.h b/weex_core/Source/core/data_render/ast_factory.h index 40c46b1361..20bdc2e265 100644 --- a/weex_core/Source/core/data_render/ast_factory.h +++ b/weex_core/Source/core/data_render/ast_factory.h @@ -40,7 +40,7 @@ class ASTFactory { virtual Handle NewExpressionList(const std::vector>& list); virtual Handle NewClassBody(); virtual Handle NewThisExpression(); - virtual Handle NewNewExpression(Handle expr); + virtual Handle NewNewExpression(Handle expr, Handle args = nullptr); virtual Handle NewIdentifier(std::string name); virtual Handle NewChunkStatement(Handle list); virtual Handle NewBlockStatement(Handle list); @@ -80,7 +80,7 @@ class ASTFactory { virtual Handle NewPostfixExpression(Position &loc, Scope *scope, PostfixOperation op, Handle expr); virtual Handle NewIntegralConstant(Position &loc, Scope *scope, int value); virtual Handle NewDoubleConstant(Position &loc, Scope *scope, double value); - virtual Handle NewNewExpression(Position &loc, Scope *scope, Handle expr); + virtual Handle NewNewExpression(Position &loc, Scope *scope, Handle expr, Handle args = nullptr); virtual Handle NewIdentifier(Position &loc, Scope *scope, std::string name); virtual Handle NewArgumentList(Position &loc, Scope *scope, Handle); virtual Handle NewCallExpression(Position &loc, Scope *scope, MemberAccessKind kind, Handle func, Handle args); @@ -88,6 +88,7 @@ class ASTFactory { virtual Handle NewMemberExpression(Position &loc, Scope *scope, MemberAccessKind kind, Handle expr, Handle mem); virtual Handle NewNullConstant(Position &loc, Scope *scope); virtual Handle NewStringConstant(Position &loc, Scope *scope, std::string str); + virtual Handle NewRegexConstant(Position &loc, Scope *scope, std::string str); virtual Handle NewThisExpression(Position &loc, Scope *scope); virtual Handle NewBooleanConstant(Position &loc, Scope *scope, bool val); virtual Handle NewArrayConstant(Position &loc, Scope *scope, ProxyArray arr); @@ -97,6 +98,13 @@ class ASTFactory { virtual Handle NewBlockStatement(Position &loc, Scope *scope, Handle list); virtual Handle NewForStatement(Position &loc, Scope *scope, ForKind kind, Handle init, Handle condition, Handle update, Handle body); virtual Handle NewBreakStatement(Position &loc, Scope *scope, Handle label = nullptr); + virtual Handle NewCaseStatement(Position &loc, Scope *scope, Handle test_value,Handle expr); + virtual Handle NewSwitchStatement(Position &loc, Scope *scope, Handle test_case, std::vector> cases); + virtual Handle NewTryCatchStatement(Position &loc, Scope *scope, + Handle try_block, + Handle catch_expr, + Handle catch_block, + Handle finally ); virtual Handle NewContinueStatement(Position &loc, Scope *scope, Handle label = nullptr); virtual Handle NewIfStatement(Position &loc, Scope *scope, Handle condition, Handle then); virtual Handle NewIfElseStatement(Position &loc, Scope *scope, Handle condition, Handle then, Handle els); @@ -108,6 +116,8 @@ class ASTFactory { virtual Handle NewArrowFunctionStatement(Position &loc, Scope *scope, Handle body, std::vector> args); virtual Handle NewJSXNodeExpression(Position &loc, Scope *scope, Handle identifier, Handle props, Handle parent, std::vector> childrens); virtual Handle NewClassStatement(Position &loc, Scope *scope, Handle identifier, Handle superClass, Handle body); + virtual Handle NewClassProperty(Position &loc, Scope *scope, std::string name, Handle init = nullptr); + }; } // namespace data_render diff --git a/weex_core/Source/core/data_render/binary_file.cc b/weex_core/Source/core/data_render/binary_file.cc deleted file mode 100644 index 549a6698b7..0000000000 --- a/weex_core/Source/core/data_render/binary_file.cc +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "core/data_render/binary_file.h" -#include "core/data_render/common_error.h" - -namespace weex { -namespace core { -namespace data_render { - BinaryFile* BinaryFile::g_instance_ = nullptr; - - BinaryFile::BinaryFile():fout_(nullptr), position_(0), length_(0) { - int32_t i=1; - char *b=(char *)&i; - if (*b == 1) { - little_endian_ = true; - } else { - little_endian_ = false; - } - } - - BinaryFile* BinaryFile::instance() { - if (!g_instance_) { - g_instance_ = new BinaryFile(); - } - return g_instance_; - } - - void BinaryFile::set_input(const char* input) { - input_ = input; - } - - void BinaryFile::set_length(unsigned long length) { - length_ = length; - } - - void BinaryFile::setWriteFileUrl(const std::string& url) { - fout_.reset(new std::ofstream(url, std::ios::binary)); - } - - void BinaryFile::write(const char *stream, unsigned count) { - fout_->write(stream, count); - } - - void BinaryFile::read(char *stream, unsigned count) { - if (position_ + count > length_) { - throw OpcodeDecodeError("Read data is error"); - } - if (!little_endian_ && count > 1) { - for (int i=count-1; i>=0; i--) { - stream[i] = input_[position_++]; - } - } else { - for (int i=0; iclose(); - } - - void BinaryFile::readFinish() { - position_ = 0; - length_ = 0; - input_ = nullptr; - } -} // namespace data_render -} // namespace core -} // namespace weex diff --git a/weex_core/Source/core/data_render/binary_file.h b/weex_core/Source/core/data_render/binary_file.h deleted file mode 100644 index e8a31acb72..0000000000 --- a/weex_core/Source/core/data_render/binary_file.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef CORE_DATA_RENDER_BINARY_FILE_H_ -#define CORE_DATA_RENDER_BINARY_FILE_H_ - -#include -#include - -namespace weex { -namespace core { -namespace data_render { - enum Section { - NULL_SECTION, - STRING_SECTION, - TABLE_SECTION, - FUNCTION_SECTION, - START_SECTION, - GLOBAL_SECTION, - GLOBAL_VARIABLE_SECTION, - STYLE_SECTION, - ARRAY_SECTION, - REF_SECTION, - CLASS_SECTION - }; - - class BinaryFile { - public: - static BinaryFile* instance(); - void set_input(const char* input); - void set_length(unsigned long length); - void setWriteFileUrl(const std::string& url); - void write(const char *stream, unsigned count); - void read(char *stream, unsigned count); - void writeFinish(); - void readFinish(); - bool eof() {return length_ == position_;} - private: - BinaryFile(); - - static BinaryFile* g_instance_; - std::unique_ptr fout_; - const char* input_; - unsigned long position_; - unsigned long length_; - bool little_endian_; - }; -} // namespace data_render -} // namespace core -} // namespace weex -#endif //CORE_DATA_RENDER_BINARY_FILE_H_ diff --git a/weex_core/Source/core/data_render/class.cc b/weex_core/Source/core/data_render/class.cc index f65cbb9434..24d39a2f2e 100644 --- a/weex_core/Source/core/data_render/class.cc +++ b/weex_core/Source/core/data_render/class.cc @@ -18,6 +18,7 @@ */ #include #include "core/data_render/class.h" +#include "core/data_render/rax_jsx_ast.h" namespace weex { namespace core { @@ -31,7 +32,7 @@ void AddClassStaticCFunc(ClassDescriptor *p_desc, const std::string& name, CFunc Value func; func.type = Value::Type::CFUNC; func.cf = reinterpret_cast(function); - p_desc->static_funcs_->Add(name, func); + p_desc->statics_->Add(name, func); } void AddClassCFunc(ClassDescriptor *p_desc, const std::string& name, CFunction function) { @@ -45,7 +46,22 @@ ClassInstance *NewClassInstance(ClassDescriptor *p_desc) { return new ClassInstance(p_desc); } -Value *GetClassMember(ClassInstance *inst, std::string &name) { +bool FindConstructor(ClassInstance *p_inst, Value *caller, Value *caller_inst) { + bool constructor = false; + while (p_inst) { + int index = p_inst->p_desc_->funcs_->IndexOf(JS_GLOBAL_CONSTRUCTOR); + if (index >= 0) { + *caller = *p_inst->p_desc_->funcs_->Find(index); + SetCIValue(caller_inst, reinterpret_cast(p_inst)); + constructor = true; + break; + } + p_inst = p_inst->p_super_; + } + return constructor; +} + +Value *GetClassMember(ClassInstance *inst,const std::string &name) { Value *ret = nullptr; do { ClassInstance *inst_current = inst; @@ -77,7 +93,7 @@ Value *GetClassMember(ClassInstance *inst, std::string &name) { return ret; } -Value *GetClassMemberVar(ClassInstance *inst, std::string &name) { +Value *GetClassMemberVar(ClassInstance *inst,const std::string &name) { Value *ret = nullptr; do { Variables *funcs = inst->p_desc_->funcs_.get(); @@ -100,6 +116,25 @@ Value *GetClassMemberVar(ClassInstance *inst, std::string &name) { return ret; } + +Value *GetClassStaticMemberVar(ClassDescriptor *desc, const std::string &name) { + Value *ret = nullptr; + do { + Variables *static_vars = desc->statics_.get(); + int index = static_vars->IndexOf(name); + if (index < 0) { + Value var; + index = static_vars->Add(name, var); + ret = static_vars->Find(index); + } + else { + ret = static_vars->Find(index); + } + + } while (0); + + return ret; +} } // namespace data_render } // namespace core diff --git a/weex_core/Source/core/data_render/class.h b/weex_core/Source/core/data_render/class.h index 134b776811..8118b5f262 100644 --- a/weex_core/Source/core/data_render/class.h +++ b/weex_core/Source/core/data_render/class.h @@ -36,11 +36,14 @@ void AddClassStaticCFunc(ClassDescriptor *p_desc, const std::string& name, CFunc void AddClassCFunc(ClassDescriptor *p_desc, const std::string& name, CFunction function); +bool FindConstructor(ClassInstance *p_inst, Value *caller, Value *caller_inst); + ClassInstance *NewClassInstance(ClassDescriptor *p_desc); -Value *GetClassMember(ClassInstance *inst, std::string &name); -Value *GetClassMemberVar(ClassInstance *inst, std::string &name); - +Value *GetClassMember(ClassInstance *inst, const std::string &name); +Value *GetClassMemberVar(ClassInstance *inst, const std::string &name); +Value *GetClassStaticMemberVar(ClassDescriptor *desc, const std::string &name); + } // namespace data_render } // namespace core } // namespace weex diff --git a/weex_core/Source/core/data_render/class_array.cc b/weex_core/Source/core/data_render/class_array.cc index 784d3722e2..0e765ebfb3 100644 --- a/weex_core/Source/core/data_render/class_array.cc +++ b/weex_core/Source/core/data_render/class_array.cc @@ -34,6 +34,7 @@ static Value push(ExecState *exec_state); static Value slice(ExecState *exec_state); static Value forEach(ExecState *exec_state); static Value indexOf(ExecState *exec_state); +static Value map(ExecState *exec_state); ClassDescriptor *NewClassArray() { ClassDescriptor *array_desc = new ClassDescriptor(nullptr); @@ -42,18 +43,9 @@ ClassDescriptor *NewClassArray() { AddClassCFunc(array_desc, "slice", slice); AddClassCFunc(array_desc, "forEach", forEach); AddClassCFunc(array_desc, "indexOf", indexOf); + AddClassCFunc(array_desc, "map", map); return array_desc; } - -int IndexOf(const std::vector &items, const Value *val) { - auto iterator = std::find(items.begin(), items.end(), val); - if (iterator != items.end()) { - return (int)std::distance(items.begin(), iterator); - } - else { - return -1; - } -} int SetArray(Array *array, Value *index, const Value &val) { int ret = 0; @@ -174,6 +166,33 @@ static Value forEach(ExecState *exec_state) { return Value(); } +static Value map(ExecState *exec_state) { + do { + size_t length = exec_state->GetArgumentCount(); + if (length < 2) { + break; + } + Value *array = exec_state->GetArgument(0); + if (!IsArray(array)) { + throw VMExecError("map caller isn't a Array"); + } + Value *func = exec_state->GetArgument(1); + if (!IsFunction(func)) { + throw VMExecError("map callback isn't a function"); + } + std::vector items = ValueTo(array)->items; + for (int i = 0; i < items.size(); i++) { + Value item = items[i]; + Value index = Value(i); + std::vector args = { item, index }; + exec_state->Call(func, args); + } + + } while (0); + + return Value(); +} + static Value indexOf(ExecState *exec_state) { int index = -1; do { diff --git a/weex_core/Source/core/data_render/class_array.h b/weex_core/Source/core/data_render/class_array.h index e74be75c3f..5eaa28813a 100644 --- a/weex_core/Source/core/data_render/class_array.h +++ b/weex_core/Source/core/data_render/class_array.h @@ -34,7 +34,7 @@ ClassDescriptor *NewClassArray(); int SetArray(Array *array, Value *index, const Value &val); int SetArray(Array *array, int index, const Value &val); Value GetArrayValue(Array *array, const Value &index); -Value* GetArrayVar(Array *array, const Value &index); +Value *GetArrayVar(Array *array, const Value &index); Value GetArraySizeValue(Array *array); size_t GetArraySize(Array *array); void ClearArray(Array *array); diff --git a/weex_core/Source/core/data_render/class_console.cc b/weex_core/Source/core/data_render/class_console.cc new file mode 100644 index 0000000000..1ca89772bc --- /dev/null +++ b/weex_core/Source/core/data_render/class_console.cc @@ -0,0 +1,134 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include +#include +#include "core/data_render/class.h" +#include "core/data_render/table.h" +#include "core/data_render/class_console.h" +#include "core/data_render/exec_state.h" +#include "core/data_render/common_error.h" +#include "core/data_render/vnode/vnode_render_manager.h" +#include "third_party/json11/json11.hpp" +#include + +namespace weex { +namespace core { +namespace data_render { + +#define WXLOG_ERROR "__ERROR" +#define WXLOG_WARN "__WARN" +#define WXLOG_INFO "__INFO" +#define WXLOG_DEBUG "__DEBUG" +#define WXLOG_LOG "__LOG" + +static Value log(ExecState *exec_state); +static Value info(ExecState *exec_state); +static Value debug(ExecState *exec_state); +static Value warn(ExecState *exec_state); +static Value error(ExecState *exec_state); + +ClassDescriptor *NewClassConsole() { + ClassDescriptor *desc = new ClassDescriptor(nullptr); + AddClassStaticCFunc(desc, "log", log); + AddClassStaticCFunc(desc, "info", info); + AddClassStaticCFunc(desc, "debug", debug); + AddClassStaticCFunc(desc, "warn", warn); + AddClassStaticCFunc(desc, "error", error); + return desc; +} + +static std::string loginfo2string(ExecState *exec_state, std::string level) { + size_t argc = exec_state->GetArgumentCount(); + std::stringstream stream; + stream << "["; + for (int i = 0; i < argc; ++i) { + Value *a = exec_state->GetArgument(i); + switch (a->type) { + case Value::Type::NIL: + stream << "null"; + break; + case Value::Type::NUMBER: + stream << a->n; + break; + case Value::Type::BOOL: + stream << (a->b ? "true" : "false"); + break; + case Value::Type::INT: + stream << a->i; + break; + case Value::Type::STRING: + stream << "\"" << a->str->c_str() << "\""; + break; + case Value::Type::TABLE: + stream << TableToString(ValueTo(a)); + break; + case Value::Type::ARRAY: + stream << ArrayToString(ValueTo(a)); + break; + case Value::Type::CLASS_DESC: + stream << "class descriptor"; + break; + case Value::Type::CLASS_INST: + stream << "class object"; + break; + case Value::Type::CPTR: + stream << "cptr"; + break; + default: + stream << "unknown type"; + break; + } + } + stream << ",\"" << level << "\"" << "]"; + return stream.str(); +} + +static Value log(ExecState *exec_state) { + const std::string& stream = loginfo2string(exec_state, WXLOG_LOG); + weex::core::data_render::VNodeRenderManager::GetInstance()->WXLogNative(exec_state, stream); + return Value(); +} + +static Value info(ExecState *exec_state) { + const std::string& stream = loginfo2string(exec_state, WXLOG_INFO); + weex::core::data_render::VNodeRenderManager::GetInstance()->WXLogNative(exec_state, stream); + return Value(); +} + +static Value debug(ExecState *exec_state) { + const std::string& stream = loginfo2string(exec_state, WXLOG_DEBUG); + weex::core::data_render::VNodeRenderManager::GetInstance()->WXLogNative(exec_state, stream); + return Value(); +} + +static Value warn(ExecState *exec_state) { + const std::string& stream = loginfo2string(exec_state, WXLOG_WARN); + weex::core::data_render::VNodeRenderManager::GetInstance()->WXLogNative(exec_state, stream); + return Value(); +} + +static Value error(ExecState *exec_state) { + const std::string& stream = loginfo2string(exec_state, WXLOG_ERROR); + weex::core::data_render::VNodeRenderManager::GetInstance()->WXLogNative(exec_state, stream); + return Value(); +} + +} // namespace data_render +} // namespace core +} // namespace weex diff --git a/weex_core/Source/core/data_render/class_console.h b/weex_core/Source/core/data_render/class_console.h new file mode 100644 index 0000000000..529ed38be5 --- /dev/null +++ b/weex_core/Source/core/data_render/class_console.h @@ -0,0 +1,39 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// +// Created by pentao.pt on 2018/7/25. +// + +#ifndef DATA_RENDER_CONSOLE_CLASS_H +#define DATA_RENDER_CONSOLE_CLASS_H + +#include "core/data_render/object.h" + +namespace weex { +namespace core { +namespace data_render { + +ClassDescriptor *NewClassConsole(); + +} // namespace data_render +} // namespace core +} // namespace weex + +#endif // DATA_RENDER_CONSOLE_CLASS_H diff --git a/weex_core/Source/core/data_render/class_factory.cc b/weex_core/Source/core/data_render/class_factory.cc index bca5d9e8a8..5e4bf0a5a8 100644 --- a/weex_core/Source/core/data_render/class_factory.cc +++ b/weex_core/Source/core/data_render/class_factory.cc @@ -8,7 +8,12 @@ #include "core/data_render/class_string.h" #include "core/data_render/class_json.h" #include "core/data_render/class_object.h" +#include "core/data_render/class_console.h" #include "core/data_render/table.h" +#include "core/data_render/exec_state.h" +#include "core/data_render/class_regex.h" +#include "core/data_render/class_window.h" +#include "class_math.h" namespace weex { namespace core { @@ -19,7 +24,6 @@ Value ClassFactory::CreateClassDescriptor(ClassDescriptor *p_super) { Value value; SetCDValue(&value, reinterpret_cast(desc)); stores_.push_back(std::make_pair(reinterpret_cast(desc), value.type)); - descs_.push_back(desc); return value; } @@ -28,7 +32,6 @@ Value ClassFactory::CreateArray() { Value value; SetAValue(&value, reinterpret_cast(array)); stores_.push_back(std::make_pair(reinterpret_cast(array), value.type)); - arrays_.push_back(array); return value; } @@ -37,7 +40,6 @@ Value ClassFactory::CreateTable() { Value value; SetTValue(&value, reinterpret_cast(table)); stores_.push_back(std::make_pair(reinterpret_cast(table), value.type)); - tables_.push_back(table); return value; } @@ -46,7 +48,6 @@ Value ClassFactory::ClassString() { Value value; SetCDValue(&value, reinterpret_cast(desc)); stores_.push_back(std::make_pair(reinterpret_cast(desc), value.type)); - descs_.push_back(desc); return value; } @@ -55,7 +56,6 @@ Value ClassFactory::ClassJSON() { Value value; SetCDValue(&value, reinterpret_cast(desc)); stores_.push_back(std::make_pair(reinterpret_cast(desc), value.type)); - descs_.push_back(desc); return value; } @@ -64,7 +64,6 @@ Value ClassFactory::ClassArray() { Value value; SetCDValue(&value, reinterpret_cast(desc)); stores_.push_back(std::make_pair(reinterpret_cast(desc), value.type)); - descs_.push_back(desc); return value; } @@ -73,13 +72,45 @@ Value ClassFactory::ClassObject() { Value value; SetCDValue(&value, reinterpret_cast(desc)); stores_.push_back(std::make_pair(reinterpret_cast(desc), value.type)); - descs_.push_back(desc); return value; } - -int ClassFactory::findDesc(const ClassDescriptor *desc) { + +Value ClassFactory::ClassRegExp() { + ClassDescriptor *desc = NewClassRegex(); + Value value; + SetCDValue(&value, reinterpret_cast(desc)); + stores_.push_back(std::make_pair(reinterpret_cast(desc), value.type)); + return value; +} + +Value ClassFactory::ClassWindow() { + ClassDescriptor *desc = NewClassWindow(); + Value value; + SetCDValue(&value, reinterpret_cast(desc)); + stores_.push_back(std::make_pair(reinterpret_cast(desc), value.type)); + return value; +} + +Value ClassFactory::ClassMath() { + ClassDescriptor *desc = NewClassMath(); + Value value; + SetCDValue(&value, reinterpret_cast(desc)); + stores_.push_back(std::make_pair(reinterpret_cast(desc), value.type)); + return value; +} + +Value ClassFactory::ClassConsole() { + ClassDescriptor *desc = NewClassConsole(); + Value value; + SetCDValue(&value, reinterpret_cast(desc)); + stores_.push_back(std::make_pair(reinterpret_cast(desc), value.type)); + return value; +} + +int ClassFactory::Find(const ClassDescriptor *desc) { + std::vector descs = this->descs(); int index = 0; - for (auto d : descs_) { + for (auto d : descs) { if (desc == d) { return index; } @@ -91,14 +122,14 @@ int ClassFactory::findDesc(const ClassDescriptor *desc) { ClassInstance *ClassFactory::CreateClassInstanceFromSuper(ClassDescriptor *p_desc) { ClassInstance *p_super = nullptr; ClassInstance *inst = NewClassInstance(p_desc); - stores_.push_back(std::make_pair(reinterpret_cast(inst), Value::Type::CLASS_INST)); if (p_desc->p_super_) { p_super = CreateClassInstanceFromSuper(p_desc->p_super_); inst->p_super_ = p_super; } + stores_.push_back(std::make_pair(reinterpret_cast(inst), Value::Type::CLASS_INST)); return inst; } - + Value ClassFactory::CreateClassInstance(ClassDescriptor *p_desc) { ClassInstance *inst = CreateClassInstanceFromSuper(p_desc); Value value; @@ -106,6 +137,14 @@ Value ClassFactory::CreateClassInstance(ClassDescriptor *p_desc) { return value; } +Value ClassFactory::CreateFuncInstance(FuncState *func_state) { + FuncInstance *func_inst = new FuncInstance(func_state); + Value value; + SetGCFuncValue(&value, reinterpret_cast(func_inst)); + stores_.push_back(std::make_pair(reinterpret_cast(func_inst), Value::Type::FUNC_INST)); + return value; +} + ClassFactory::~ClassFactory() { for (auto iter = stores_.begin(); iter != stores_.end(); iter++) { switch (iter->second) { @@ -129,13 +168,56 @@ ClassFactory::~ClassFactory() { delete reinterpret_cast(iter->first); break; } + case Value::Type::FUNC_INST: + { + FuncInstance *inst = reinterpret_cast(iter->first); + for (int i = 0; i < inst->closures_.size(); i++) { + delete inst->closures_[i]; + } + delete inst; + break; + } default: break; } } stores_.clear(); } +std::vector ClassFactory::descs() { + std::vector descs; + for (auto iter = stores_.begin(); iter != stores_.end(); iter++) { + if (iter->second == Value::Type::CLASS_DESC) { + descs.push_back(reinterpret_cast(iter->first)); + } + } + return descs; +} +std::vector ClassFactory::constants() { + std::vector constants; + for (auto iter = stores_.begin(); iter != stores_.end(); iter++) { + switch (iter->second) { + case Value::Type::ARRAY: + { + Value array; + SetAValue(&array, iter->first); + constants.push_back(array); + break; + } + case Value::Type::TABLE: + { + Value table; + SetTValue(&table, iter->first); + constants.push_back(table); + break; + } + default: + break; + } + } + return constants; +} + } } } diff --git a/weex_core/Source/core/data_render/class_factory.h b/weex_core/Source/core/data_render/class_factory.h index 5a09922c63..a0b96797ce 100644 --- a/weex_core/Source/core/data_render/class_factory.h +++ b/weex_core/Source/core/data_render/class_factory.h @@ -33,30 +33,27 @@ namespace data_render { class ClassFactory { public: ClassFactory() {}; + ~ClassFactory(); virtual Value CreateClassDescriptor(ClassDescriptor *p_super); virtual Value CreateClassInstance(ClassDescriptor *p_desc); + virtual Value CreateFuncInstance(FuncState *func_state); virtual Value ClassArray(); virtual Value ClassString(); virtual Value ClassJSON(); virtual Value ClassObject(); + virtual Value ClassRegExp(); + virtual Value ClassWindow(); + virtual Value ClassMath(); + virtual Value ClassConsole(); virtual Value CreateArray(); virtual Value CreateTable(); - int findDesc(const ClassDescriptor *desc); - inline const std::vector>& stores() {return stores_;} - inline std::vector arrays() {return arrays_;} - inline std::vector descs() {return descs_;} - inline std::vector
tables() {return tables_;} - - ~ClassFactory(); - -private: + int Find(const ClassDescriptor *desc); + inline const std::vector>& stores() { return stores_; } + std::vector descs(); + std::vector constants(); + private: ClassInstance *CreateClassInstanceFromSuper(ClassDescriptor *p_desc); std::vector> stores_; - - //for binary encode and decode - std::vector descs_; - std::vector arrays_; - std::vector
tables_; }; } diff --git a/weex_core/Source/core/data_render/class_function.cc b/weex_core/Source/core/data_render/class_function.cc new file mode 100644 index 0000000000..39340faa10 --- /dev/null +++ b/weex_core/Source/core/data_render/class_function.cc @@ -0,0 +1,72 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "core/data_render/class.h" +#include "core/data_render/class_function.h" +#include "core/data_render/exec_state.h" +#include "core/data_render/common_error.h" +#include + +namespace weex { +namespace core { +namespace data_render { + +void AddClosure(ExecState *exec_state, Value *func) { + do { + if (!IsFuncInstance(func)) { + throw VMExecError("add function closure type error"); + break; + } + FuncInstance *inst = ValueTo(func); + FuncState *func_state = inst->func_; + for (int i = 0; i < func_state->in_closure().size(); i++) { + ValueRef *ref = func_state->in_closure()[i]; + FuncClosure *closure = new FuncClosure(ref); + ref->SetClosure(closure); + inst->closures_.push_back(closure); + } + + } while (0); +} + +Value *LoadClosure(Value *func, ValueRef *ref) { + Value *ret = nullptr; + do { + if (!IsFuncInstance(func)) { + throw VMExecError("load function closure type error"); + break; + } + FuncInstance *inst = ValueTo(func); + for (int i = 0; i < inst->closures_.size(); i++) { + FuncClosure *closure = inst->closures_[i]; + if (closure->func_state() == ref->func_state() && closure->register_id() == ref->register_id()) { + ret = &closure->value(); + break; + } + } + + } while (0); + + return ret; +} + +} // namespace data_render +} // namespace core +} // namespace weex diff --git a/weex_core/Source/core/data_render/class_function.h b/weex_core/Source/core/data_render/class_function.h new file mode 100644 index 0000000000..5278f794fa --- /dev/null +++ b/weex_core/Source/core/data_render/class_function.h @@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// +// Created by pentao.pt on 2018/7/25. +// + +#ifndef DATA_RENDER_FUNCTION_CLASS_H +#define DATA_RENDER_FUNCTION_CLASS_H + +#include "core/data_render/object.h" + +namespace weex { +namespace core { +namespace data_render { + +void AddClosure(ExecState *exec_state, Value *func); +Value *LoadClosure(Value *func, ValueRef *ref); + +} // namespace data_render +} // namespace core +} // namespace weex + +#endif // DATA_RENDER_FUNCTION_CLASS_H diff --git a/weex_core/Source/core/data_render/class_json.cc b/weex_core/Source/core/data_render/class_json.cc index 4bdf20142e..848686e1d8 100644 --- a/weex_core/Source/core/data_render/class_json.cc +++ b/weex_core/Source/core/data_render/class_json.cc @@ -22,6 +22,7 @@ #include "core/data_render/exec_state.h" #include "core/data_render/common_error.h" #include "core/data_render/table.h" +#include "core/data_render/vnode/vnode_exec_env.h" #include namespace weex { @@ -29,10 +30,12 @@ namespace core { namespace data_render { static Value stringify(ExecState *exec_state); +static Value parse(ExecState *exec_state); ClassDescriptor *NewClassJSON() { ClassDescriptor *array_desc = new ClassDescriptor(nullptr); AddClassStaticCFunc(array_desc, "stringify", stringify); + AddClassStaticCFunc(array_desc, "parse", parse); return array_desc; } @@ -61,6 +64,26 @@ static Value stringify(ExecState *exec_state) { return ret; } +static Value parse(ExecState *exec_state) { + Value ret; + do { + size_t length = exec_state->GetArgumentCount(); + if (length < 1) { + break; + } + Value *value = exec_state->GetArgument(0); + if (!IsString(value)) { + throw VMExecError("json parse caller isn't a String"); + } + std::string json_string = CStringValue(value); + ret = StringToValue(exec_state, json_string); + + } while (0); + + return ret; + +} + } // namespace data_render } // namespace core } // namespace weex diff --git a/weex_core/Source/core/data_render/class_math.cc b/weex_core/Source/core/data_render/class_math.cc new file mode 100644 index 0000000000..119f1b1206 --- /dev/null +++ b/weex_core/Source/core/data_render/class_math.cc @@ -0,0 +1,137 @@ +// +// Created by Xu Jiacheng on 2018/11/6. +// + +#include "core/data_render/class_math.h" +#include "core/data_render/exec_state.h" +#include "core/data_render/class.h" +#include "core/data_render/common_error.h" +#include "third_party/json11/json11.hpp" +#include "vnode/vnode_render_manager.h" + +namespace weex { +namespace core { +namespace data_render { + +static Value Ceil(ExecState* exec_state){ + size_t argc = exec_state->GetArgumentCount(); + if (argc!=1){ + throw VMExecError("math.ceil takes more than one args"); + } + Value* value = exec_state->GetArgument(0); + if(!IsNumber(value)&&!IsInt(value)){ + throw VMExecError("math.ceil arg not number"); + } + + if (IsNumber(value)){ + return static_cast(ceil(NumValue(value))); + } else { + return static_cast(ceil(IntValue(value))); + } +} + +static Value Floor(ExecState* exec_state){ + size_t argc = exec_state->GetArgumentCount(); + if (argc!=1){ + throw VMExecError("math.ceil takes more than one args"); + } + Value* value = exec_state->GetArgument(0); + if(!IsNumber(value)&&!IsInt(value)){ + throw VMExecError("math.ceil arg not number"); + } + + if (IsNumber(value)){ + return static_cast(floor(NumValue(value))); + } else { + return static_cast(floor(IntValue(value))); + } +} + + +static Value Random(ExecState* exec_state){ + return static_cast (rand()) / static_cast (RAND_MAX); +} + +static Value Max(ExecState* exec_state){ + size_t argc = exec_state->GetArgumentCount(); + if (argc <= 1){ + return Value(INT64_MIN); + } + + double max = std::numeric_limits::lowest(); + int index = -1; + + for (int i = 0; i < argc; ++i) { + auto value = exec_state->GetArgument(i); + if (IsInt(value)){ + int64_t value_i = IntValue(value); + if (value_i>max){ + index = i; + max = static_cast(value_i); + } + } else if (IsNumber(value)){ + double value_d = NumValue(value); + if (value_d>max){ + index = i; + max = value_d; + } + } else { + return Value(); + } + } + + if (index>=0){ + return Value(*exec_state->GetArgument(index)); + } else{ + return Value(INT64_MIN); + } +} + +static Value Min(ExecState* exec_state){ + size_t argc = exec_state->GetArgumentCount(); + if (argc <= 1){ + return Value(INT64_MAX); + } + + double min = std::numeric_limits::max(); + int index = -1; + + for (int i = 0; i < argc; ++i) { + auto value = exec_state->GetArgument(i); + if (IsInt(value)){ + int64_t value_i = IntValue(value); + if (value_i(value_i); + } + } else if (IsNumber(value)){ + double value_d = NumValue(value); + if (value_d=0){ + return Value(*exec_state->GetArgument(index)); + } else{ + return Value(INT64_MAX); + } +} + +ClassDescriptor* NewClassMath() { + ClassDescriptor *desc = new ClassDescriptor(nullptr); + AddClassStaticCFunc(desc, "ceil", Ceil); + AddClassStaticCFunc(desc, "floor", Floor); + AddClassStaticCFunc(desc, "random", Random); + AddClassStaticCFunc(desc, "max", Max); + AddClassStaticCFunc(desc, "min", Min); + return desc; +} + +} // namespace data_render +} // namespace core +} // namespace weex diff --git a/weex_core/Source/core/data_render/class_math.h b/weex_core/Source/core/data_render/class_math.h new file mode 100644 index 0000000000..6631884a1f --- /dev/null +++ b/weex_core/Source/core/data_render/class_math.h @@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +// +// Created by Xu Jiacheng on 2018/11/6. +// + +#ifndef WEEX_PROJECT_CLASS_MATH_H +#define WEEX_PROJECT_CLASS_MATH_H + + +#include "object.h" + +namespace weex { +namespace core { +namespace data_render { + +ClassDescriptor *NewClassMath(); + +} // namespace data_render +} // namespace core +} // namespace weex + + +#endif //WEEX_PROJECT_CLASS_MATH_H diff --git a/weex_core/Source/core/data_render/class_regex.cc b/weex_core/Source/core/data_render/class_regex.cc new file mode 100644 index 0000000000..43c033a7c3 --- /dev/null +++ b/weex_core/Source/core/data_render/class_regex.cc @@ -0,0 +1,146 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include +#include +#include +#include "core/data_render/class.h" +#include "core/data_render/class_regex.h" +#include "core/data_render/exec_state.h" +#include "core/data_render/common_error.h" +#include "core/data_render/table.h" +#include + +namespace weex { +namespace core { +namespace data_render { + +static Value test(ExecState *exec_state); +static Value exec(ExecState *exec_state); + +ClassDescriptor *NewClassRegex() { + ClassDescriptor *desc = new ClassDescriptor(nullptr); + AddClassCFunc(desc, "test", test); + AddClassCFunc(desc, "exec", exec); + return desc; +} + +static Value test(ExecState *exec_state) { + Value ret; + do { + size_t length = exec_state->GetArgumentCount(); + if (length != 2) { + throw VMExecError("Regex.test arg count != 2"); + } + Value *caller = exec_state->GetArgument(0); + Value *arg = exec_state->GetArgument(1); + if (!IsClassInstance(caller)) { + throw VMExecError("Type Error For Class Instance with OP_CODE [OP_GETSUPER]"); + } + ClassInstance *inst = ValueTo(caller); + + Value* reg = GetClassMember(inst, "_reg"); + Value* flag = GetClassMember(inst, "_flag"); + if (!IsString(reg) || !IsString(flag) || !IsString(arg)){ + throw VMExecError("Regex._reg || _flag is not string"); + } + std::string reg_str = ValueTo(reg)->c_str(); + std::string flag_str = ValueTo(flag)->c_str(); + std::string test_str = ValueTo(arg)->c_str(); + + std::regex_constants::syntax_option_type type = std::regex_constants::ECMAScript; + if (flag_str.find('i') != std::string::npos){ + type |= std::regex_constants::icase; + } + std::regex express(reg_str, type); + std::smatch match; + ret = std::regex_search(test_str,match,express); + } while (0); + + return ret; +} + +static Value exec(ExecState *exec_state) { + Value ret; + do { + size_t length = exec_state->GetArgumentCount(); + if (length != 2) { + throw VMExecError("Regex.exec arg count != 2"); + } + Value *caller = exec_state->GetArgument(0); + Value *arg = exec_state->GetArgument(1); + if (!IsClassInstance(caller)) { + throw VMExecError("Type Error For Class Instance with OP_CODE [OP_GETSUPER]"); + } + ClassInstance *inst = ValueTo(caller); + + Value* reg = GetClassMember(inst, "_reg"); + Value* flag = GetClassMember(inst, "_flag"); + if (!IsString(reg) || !IsString(flag) || !IsString(arg)){ + throw VMExecError("Regex._reg || _flag is not string"); + } + std::string reg_str = ValueTo(reg)->c_str(); + std::string flag_str = ValueTo(flag)->c_str(); + std::string test_str = ValueTo(arg)->c_str(); + + std::regex_constants::syntax_option_type type = std::regex_constants::ECMAScript; + if (flag_str.find('i') != std::string::npos){ + type |= std::regex_constants::icase; + } + + bool g_mode =flag_str.find('g') != std::string::npos; + + ret = exec_state->class_factory()->CreateArray(); + Array* arr = ValueTo(&ret); + + if (g_mode){ + std::regex express(reg_str, type); + std::smatch match; + std::string::const_iterator iterStart = test_str.begin(); + std::string::const_iterator iterEnd = test_str.end(); + bool succ = false; + while (std::regex_search(iterStart,iterEnd,match,express)){ + arr->items.push_back(exec_state->string_table()->StringFromUTF8(match[0])); + iterStart = match[0].second; + succ = true; + } + if (!succ){ + ret = Value(); + } + } else{ + std::regex express(reg_str, type); + std::smatch match; + bool succ = std::regex_search(test_str,match,express); + + if (succ){ + for (size_t i = 0; i < match.size(); ++i){ + arr->items.push_back(exec_state->string_table()->StringFromUTF8(match[i])); + } + } else { + ret = Value(); + } + // else return [] + } + } while (0); + + return ret; +} + +} // namespace data_render +} // namespace core +} // namespace weex diff --git a/weex_core/Source/core/data_render/class_regex.h b/weex_core/Source/core/data_render/class_regex.h new file mode 100644 index 0000000000..2cdd522d29 --- /dev/null +++ b/weex_core/Source/core/data_render/class_regex.h @@ -0,0 +1,39 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// +// Created by pentao.pt on 2018/7/25. +// + +#ifndef DATA_RENDER_REGEX_CLASS_H +#define DATA_RENDER_REGEX_CLASS_H + +#include "core/data_render/object.h" + +namespace weex { +namespace core { +namespace data_render { + +ClassDescriptor *NewClassRegex(); + +} // namespace data_render +} // namespace core +} // namespace weex + +#endif // DATA_RENDER_JSON_CLASS_H diff --git a/weex_core/Source/core/data_render/class_string.cc b/weex_core/Source/core/data_render/class_string.cc index 61a18aee46..c98075efc4 100644 --- a/weex_core/Source/core/data_render/class_string.cc +++ b/weex_core/Source/core/data_render/class_string.cc @@ -18,6 +18,7 @@ */ #include +#include #include #include "core/data_render/class_string.h" #include "core/data_render/class.h" @@ -35,17 +36,54 @@ namespace data_render { static Value split(ExecState *exec_state); static Value trim(ExecState* exec_state); static Value indexOf(ExecState* exec_state); +static Value search(ExecState* exec_state); static Value replaceAll(ExecState *exec_state); +static Value replace(ExecState *exec_state); +static Value match(ExecState *exec_state); + +static ClassInstance* to_regex_inst(ExecState *exec_state, Value* v){ + if (!IsClassInstance(v)){ + throw VMExecError("not a regex instance"); + } + ClassInstance* instance = ValueTo(v); + int index = exec_state->global()->IndexOf("RegExp"); + if (index < 0) { + throw VMExecError("split lost RegExp define"); + } + Value* reg_define = exec_state->global()->Find(index); + if (!IsClass(reg_define)) { + throw VMExecError("split not a RegExp define"); + } + if (instance->p_desc_ != ValueTo(reg_define)) { + throw VMExecError("split not a RegExp instance"); + } + return instance; +} + +std::vector split_regex(const std::string& input, const std::string& regex, const std::string& flag) { + // passing -1 as the submatch index parameter performs splitting + std::regex_constants::syntax_option_type type = std::regex_constants::ECMAScript; + if (flag.find('i') != std::string::npos){ + type |= std::regex_constants::icase; + } + + std::regex re(regex,type); + std::sregex_token_iterator first{input.begin(), input.end(), re, -1}, last; + return {first, last}; +} ClassDescriptor *NewClassString() { ClassDescriptor *array_desc = new ClassDescriptor(nullptr); AddClassCFunc(array_desc, "split", split); AddClassCFunc(array_desc, "trim", trim); AddClassCFunc(array_desc, "indexOf", indexOf); + AddClassCFunc(array_desc, "search", search); + AddClassCFunc(array_desc, "replace", replace); AddClassCFunc(array_desc, "replaceAll", replaceAll); + AddClassCFunc(array_desc, "match", match); return array_desc; } - + std::string& replace_all(std::string& str, std::string& old_value, std::string& new_value) { while (true) @@ -60,7 +98,16 @@ std::string& replace_all(std::string& str, std::string& old_value, std::string& } return str; } - + +std::string& replace_normal(std::string& str, std::string& old_value, std::string& new_value) +{ + std::string::size_type pos(0); + if ((pos = str.find(old_value)) != std::string::npos) { + str.replace(pos, old_value.length(),new_value); + } + return str; +} + static Value replaceAll(ExecState *exec_state) { Value ret; do { @@ -85,12 +132,61 @@ static Value replaceAll(ExecState *exec_state) { std::string newstr = CStringValue(newValue); std::string dststr = replace_all(srcstr, oldstr, newstr); ret = exec_state->string_table()->StringFromUTF8(dststr); - + } while (0); - + return ret; } - + +static Value replace(ExecState *exec_state) { + Value ret; + do { + size_t length = exec_state->GetArgumentCount(); + if (length < 3) { + break; + } + Value *src = exec_state->GetArgument(0); + if (!IsString(src)) { + throw VMExecError("replaceAll caller isn't a string"); + } + Value *oldValue = exec_state->GetArgument(1); + Value *newValue = exec_state->GetArgument(2); + if (!IsString(newValue)) { + throw VMExecError("new value isn't a string"); + } + std::string srcstr = CStringValue(src); + std::string newstr = CStringValue(newValue); + if (IsString(oldValue)) { + + std::string oldstr = CStringValue(oldValue); + std::string dststr = replace_normal(srcstr, oldstr, newstr); + ret = exec_state->string_table()->StringFromUTF8(dststr); + } else if (IsClassInstance(oldValue)){ + ClassInstance* instance = to_regex_inst(exec_state,oldValue); + Value* reg = GetClassMember(instance, "_reg"); + Value* flag = GetClassMember(instance, "_flag"); + if (!IsString(reg) || !IsString(flag)){ + throw VMExecError("Regex._reg || _flag is not string"); + } + std::string reg_str = ValueTo(reg)->c_str(); + std::string flag_str = ValueTo(flag)->c_str(); + + std::regex_constants::syntax_option_type type = std::regex_constants::ECMAScript; + if (flag_str.find('i') != std::string::npos){ + type |= std::regex_constants::icase; + } + std::regex express(reg_str, type); + + std::string dststr = std::regex_replace(srcstr, express, newstr,std::regex_constants::format_first_only); + ret = exec_state->string_table()->StringFromUTF8(dststr); + } else{ + throw VMExecError("old caller isn't a string or regex"); + } + } while (0); + + return ret; +} + template void split_string(const std::string& str, Container& container, const std::string& delims = " ") { @@ -105,7 +201,7 @@ void split_string(const std::string& str, Container& container, const std::strin container.push_back(str.substr(previous, str.length() - previous)); } } - + static Value split(ExecState *exec_state) { Value ret = exec_state->class_factory()->CreateArray(); do { @@ -118,29 +214,47 @@ static Value split(ExecState *exec_state) { throw VMExecError("split caller isn't a string"); } Value *split = exec_state->GetArgument(1); - if (!IsString(split)) { - throw VMExecError("split caller isn't a string"); - } - std::string src = CStringValue(string); - std::string delim = CStringValue(split); - std::vectorsplit_array; - split_string>(src, split_array, delim); - Array *array = ValueTo(&ret); - for (int i = 0; i < split_array.size(); i++) { - Value string_value = exec_state->string_table()->StringFromUTF8(split_array[i]); - array->items.push_back(string_value); + if (IsString(split)) { + std::string src = CStringValue(string); + std::string delim = CStringValue(split); + std::vectorsplit_array; + split_string>(src, split_array, delim); + Array *array = ValueTo(&ret); + for (int i = 0; i < split_array.size(); i++) { + Value string_value = exec_state->string_table()->StringFromUTF8(split_array[i]); + array->items.push_back(string_value); + } + } else if(IsClassInstance(split)){ + ClassInstance* instance = to_regex_inst(exec_state,split); + Value* reg = GetClassMember(instance, "_reg"); + Value* flag = GetClassMember(instance, "_flag"); + if (!IsString(reg) || !IsString(flag) || !IsString(string)){ + throw VMExecError("Regex._reg || _flag is not string"); + } + std::string reg_str = ValueTo(reg)->c_str(); + std::string flag_str = ValueTo(flag)->c_str(); + std::string test_str = ValueTo(string)->c_str(); + + auto ret_vec = split_regex(test_str,reg_str,flag_str); + + Array *array = ValueTo(&ret); + for(auto st: ret_vec){ + Value string_value = exec_state->string_table()->StringFromUTF8(st); + array->items.push_back(string_value); + } + } else { + throw VMExecError("split caller isn't a string or regex"); } - } while (0); - + return ret; } - + std::string& trim(std::string &s) { if (s.empty()) { return s; } - + s.erase(0, s.find_first_not_of(" ")); s.erase(s.find_last_not_of(" ") + 1); return s; @@ -155,14 +269,14 @@ static Value trim(ExecState* exec_state) { if (!IsString(string)) { throw VMExecError("trim caller isn't a string"); } - + std::string src = CStringValue(string); trim(src); - + Value string_value = exec_state->string_table()->StringFromUTF8(src); return string_value; } - + /* Converts a hex character to its integer value */ char from_hex(char ch) { return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; @@ -190,7 +304,7 @@ char *url_encode(char *str) { *pbuf = '\0'; return buf; } - + /* Returns a url-decoded version of str */ /* IMPORTANT: be sure to free() the returned string after use */ char *url_decode(char *str) { @@ -211,7 +325,7 @@ char *url_decode(char *str) { *pbuf = '\0'; return buf; } - + Value encodeURIComponent(ExecState *exec_state) { size_t length = exec_state->GetArgumentCount(); if (length < 1) { @@ -320,6 +434,120 @@ Value indexOf(ExecState* exec_state) { return Value(static_cast(pos)); } + +Value search(ExecState* exec_state) { + Value ret; + size_t length = exec_state->GetArgumentCount(); + if (length != 2) { + throw VMExecError("search arg count wrong"); + } + + Value *string = exec_state->GetArgument(0); + if (!IsString(string)) { + throw VMExecError("split caller isn't a string"); + } + + Value *search_str = exec_state->GetArgument(1); + if(IsClassInstance(search_str)){ + ClassInstance* instance = to_regex_inst(exec_state,search_str); + + Value* reg = GetClassMember(instance, "_reg"); + Value* flag = GetClassMember(instance, "_flag"); + if (!IsString(reg) || !IsString(flag)){ + throw VMExecError("Regex._reg || _flag is not string"); + } + std::string reg_str = ValueTo(reg)->c_str(); + std::string flag_str = ValueTo(flag)->c_str(); + std::string test_str = ValueTo(string)->c_str(); + + std::regex_constants::syntax_option_type type = std::regex_constants::ECMAScript; + if (flag_str.find('i') != std::string::npos){ + type |= std::regex_constants::icase; + } + std::regex express(reg_str, type); + std::smatch match; + bool succ = std::regex_search(test_str,match,express); + if (succ){ + ret = static_cast(match.position(0)); + } else{ + ret = -1; + } + } else { + throw VMExecError("split caller isn't a string or regex"); + } + + return ret; +} + +Value match(ExecState* exec_state) { + Value ret; + size_t length = exec_state->GetArgumentCount(); + if (length != 2) { + throw VMExecError("search arg count wrong"); + } + + Value *string = exec_state->GetArgument(0); + if (!IsString(string)) { + throw VMExecError("split caller isn't a string"); + } + + Value *search_str = exec_state->GetArgument(1); + if(IsClassInstance(search_str)){ + ClassInstance* instance = to_regex_inst(exec_state,search_str); + + Value* reg = GetClassMember(instance, "_reg"); + Value* flag = GetClassMember(instance, "_flag"); + if (!IsString(reg) || !IsString(flag)){ + throw VMExecError("Regex._reg || _flag is not string"); + } + std::string reg_str = ValueTo(reg)->c_str(); + std::string flag_str = ValueTo(flag)->c_str(); + std::string test_str = ValueTo(string)->c_str(); + + std::regex_constants::syntax_option_type type = std::regex_constants::ECMAScript; + if (flag_str.find('i') != std::string::npos){ + type |= std::regex_constants::icase; + } + + bool g_mode =flag_str.find('g') != std::string::npos; + + ret = exec_state->class_factory()->CreateArray(); + Array* arr = ValueTo(&ret); + + if (g_mode){ + std::regex express(reg_str, type); + std::smatch match; + std::string::const_iterator iterStart = test_str.begin(); + std::string::const_iterator iterEnd = test_str.end(); + bool succ = false; + while (std::regex_search(iterStart,iterEnd,match,express)){ + arr->items.push_back(exec_state->string_table()->StringFromUTF8(match[0])); + iterStart = match[0].second; + succ = true; + } + if (!succ){ + ret = Value(); + } + } else{ + std::regex express(reg_str, type); + std::smatch match; + bool succ = std::regex_search(test_str,match,express); + + if (succ){ + for (size_t i = 0; i < match.size(); ++i){ + arr->items.push_back(exec_state->string_table()->StringFromUTF8(match[i])); + } + } else { + ret = Value(); + } + // else return [] + } + } else { + throw VMExecError("split caller isn't a string or regex"); + } + + return ret; +} } // namespace data_render } // namespace core } // namespace weex diff --git a/weex_core/Source/core/data_render/class_window.cc b/weex_core/Source/core/data_render/class_window.cc new file mode 100644 index 0000000000..db1e75ab41 --- /dev/null +++ b/weex_core/Source/core/data_render/class_window.cc @@ -0,0 +1,47 @@ +// +// Created by Xu Jiacheng on 2018/11/6. +// + +#include "core/data_render/class_window.h" +#include "core/data_render/exec_state.h" +#include "core/data_render/class.h" +#include "core/data_render/common_error.h" +#include "third_party/json11/json11.hpp" +#include "vnode/vnode_render_manager.h" + +namespace weex { +namespace core { +namespace data_render { + +static Value Open(ExecState *exec_state){ + size_t argc = exec_state->GetArgumentCount(); + if (argc!=1){ + throw VMExecError("window.open takes more than one args"); + } + Value* url_value = exec_state->GetArgument(0); + if(!IsString(url_value)){ + throw VMExecError("window.open arg not string"); + } + json11::Json::array args_array; + json11::Json::object obj{ + {"url",CStringValue(url_value)}, + {"animated", "true"}, + }; + args_array.push_back(obj); + + const std::string& args = json11::Json(args_array).dump(); + weex::core::data_render::VNodeRenderManager::GetInstance() + ->CallNativeModule(exec_state, "navigator", "push", args, 2); + + return Value(); +} + +ClassDescriptor* NewClassWindow() { + ClassDescriptor *desc = new ClassDescriptor(nullptr); + AddClassStaticCFunc(desc, "open", Open); + return desc; +} + +} // namespace data_render +} // namespace core +} // namespace weex diff --git a/weex_core/Source/core/data_render/class_window.h b/weex_core/Source/core/data_render/class_window.h new file mode 100644 index 0000000000..4752bb49d1 --- /dev/null +++ b/weex_core/Source/core/data_render/class_window.h @@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +// +// Created by Xu Jiacheng on 2018/11/6. +// + +#ifndef WEEX_PROJECT_CLASS_WINDOW_H +#define WEEX_PROJECT_CLASS_WINDOW_H + + +#include "object.h" + +namespace weex { +namespace core { +namespace data_render { + +ClassDescriptor *NewClassWindow(); + +} // namespace data_render +} // namespace core +} // namespace weex + + +#endif //WEEX_PROJECT_CLASS_WINDOW_H diff --git a/weex_core/Source/core/data_render/code_generator.cc b/weex_core/Source/core/data_render/code_generator.cc index bb1816b74b..1cbc4e541a 100644 --- a/weex_core/Source/core/data_render/code_generator.cc +++ b/weex_core/Source/core/data_render/code_generator.cc @@ -21,6 +21,7 @@ #include "core/data_render/exec_state.h" #include "core/data_render/string_table.h" #include "core/data_render/common_error.h" +#include "core/data_render/class.h" namespace weex { namespace core { @@ -117,11 +118,51 @@ void CodeGenerator::Visit(StringConstant* node, void* data) { FuncState *func_state = func_->func_state(); auto value = exec_state_->string_table_->StringFromUTF8(node->string()); int index = func_state->AddConstant(std::move(value)); - Instruction i = CREATE_ABx(OpCode::OP_LOADK, reg, index); + Instruction i = CREATE_ABx(OP_LOADK, reg, index); func_state->AddInstruction(i); } } +void CodeGenerator::Visit(RegexConstant* node, void* data) { + RegisterScope scope(block_); + + long reg = data == nullptr ? -1 : *static_cast(data); + if (reg >= 0) { + FuncState *func_state = func_->func_state(); + auto reg_ex = exec_state_->string_table_->StringFromUTF8(node->reg()); + auto flag = exec_state_->string_table_->StringFromUTF8(node->flag()); + auto reg_mem_name = exec_state_->string_table_->StringFromUTF8("_reg"); + auto flag_mem_name = exec_state_->string_table_->StringFromUTF8("_flag"); + + int r_index = func_state->AddConstant(std::move(reg_ex)); + int f_index = func_state->AddConstant(std::move(flag)); + int mr_index = func_state->AddConstant(std::move(reg_mem_name)); + int mf_index = func_state->AddConstant(std::move(flag_mem_name)); + auto reg_class_index = exec_state_->global()->IndexOf("RegExp"); + + auto mr_id = block_->NextRegisterId(); + auto mf_id = block_->NextRegisterId(); + auto r_id = block_->NextRegisterId(); + auto f_id = block_->NextRegisterId(); + auto class_id = block_->NextRegisterId(); + auto tmp = block_->NextRegisterId(); + + func_state->AddInstruction(CREATE_ABx(OP_LOADK, mr_id, mr_index)); + func_state->AddInstruction(CREATE_ABx(OP_LOADK, mf_id, mf_index)); + func_state->AddInstruction(CREATE_ABx(OP_LOADK, r_id, r_index)); + func_state->AddInstruction(CREATE_ABx(OP_LOADK, f_id, f_index)); + func_state->AddInstruction(CREATE_ABx(OP_GETGLOBAL, class_id, reg_class_index)); + + func_state->AddInstruction(CREATE_ABC(OP_NEW, reg, Value::Type::CLASS_DESC, class_id)); + + func_state->AddInstruction(CREATE_ABC(OP_GETMEMBERVAR, tmp, reg, mr_id)); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, tmp, r_id)); + + func_state->AddInstruction(CREATE_ABC(OP_GETMEMBERVAR, tmp, reg, mf_id)); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, tmp, f_id)); + } +} + void CodeGenerator::Visit(ExpressionList* node, void* data) { for (auto it = node->raw_list().begin(); it != node->raw_list().end(); ++it) { auto temp = (*it).get(); @@ -157,19 +198,19 @@ void CodeGenerator::Visit(CallExpression *stms, void *data) { if (block_->idx() > caller + 1) { long reg_old_caller = caller; caller = block_->NextRegisterId(); - func_state->AddInstruction(CREATE_ABC(OP_MOVE, caller, reg_old_caller, 0)); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, caller, reg_old_caller)); } caller_regs_order.push_back(caller); } else if (stms->expr().get()) { - if (class_ && stms->expr()->IsIdentifier() && stms->expr()->AsIdentifier()->GetName() == "super") + if (class_ && stms->expr()->IsIdentifier() && stms->expr()->AsIdentifier()->GetName() == JS_GLOBAL_SUPER) { ClassDescriptor *class_desc = ValueTo(class_->class_value()); if (!class_desc->p_super_) { throw GeneratorError("can't call super without class desc"); } ClassDescriptor *class_desc_super = class_desc->p_super_; - int index = class_desc_super->funcs_->IndexOf("constructor"); + int index = class_desc_super->funcs_->IndexOf(JS_GLOBAL_CONSTRUCTOR); if (index < 0) { throw GeneratorError("can't call super without class desc"); } @@ -210,7 +251,7 @@ void CodeGenerator::Visit(CallExpression *stms, void *data) { if (block_->idx() > caller + 1) { long reg_old_caller = caller; caller = block_->NextRegisterId(); - func_state->AddInstruction(CREATE_ABC(OP_MOVE, caller, reg_old_caller, 0)); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, caller, reg_old_caller)); } caller_regs_order.push_back(caller); if (stms->expr()->IsMemberExpression()) { @@ -250,35 +291,40 @@ void CodeGenerator::Visit(CallExpression *stms, void *data) { } argc += arg_list->length(); } - FuncState *state = func_->func_state(); - bool call_reorder = false; - int regs_count = (int)caller_regs_order.size(); + AddCallInstruction(ret, OP_CALL, caller_regs_order); +} + +void CodeGenerator::AddCallInstruction(long ret, OPCode code, std::vector orders) { + FuncState *func_state = func_->func_state(); + bool reorder = false; + int regs_count = static_cast(orders.size()); for (int i = 1; i < regs_count; i++) { - if (caller_regs_order[i] - caller_regs_order[i - 1] != 1) { - call_reorder = true; + if (orders[i] - orders[i - 1] != 1) { + reorder = true; break; } } - if (!call_reorder && regs_count > 0) { - call_reorder = caller_regs_order[regs_count - 1] + 1 >= block_->idx() ? false : true; + if (!reorder && regs_count > 0) { + reorder = orders[regs_count - 1] + 1 >= block_->idx() ? false : true; } - if (call_reorder) { - caller = block_->NextRegisterId(); - func_state->AddInstruction(CREATE_ABC(OP_MOVE, caller, caller_regs_order[0], 0)); - for (int i = 1; i < caller_regs_order.size(); i++) { + int argc = regs_count - 1; + if (reorder) { + long caller = block_->NextRegisterId(); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, caller, orders[0])); + for (int i = 1; i < orders.size(); i++) { long arg = block_->NextRegisterId(); - func_state->AddInstruction(CREATE_ABC(OP_MOVE, arg, caller_regs_order[i], 0)); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, arg, orders[i])); } - state->AddInstruction(CREATE_ABC(OP_CALL, ret, argc, caller)); + func_state->AddInstruction(CREATE_ABC(code, ret, argc, caller)); } else { - state->AddInstruction(CREATE_ABC(OP_CALL, ret, argc, caller)); + func_state->AddInstruction(CREATE_ABC(code, ret, argc, orders[0])); } } -void CodeGenerator::Visit(ArgumentList* node, void* data) { - Handle exprList = node->args(); - exprList->Accept(this, data); +void CodeGenerator::Visit(ArgumentList *node, void *data) { + Handle exprList = node->args(); + exprList->Accept(this, data); } void CodeGenerator::Visit(IfStatement *node, void *data) { @@ -430,15 +476,24 @@ void CodeGenerator::Visit(FunctionStatement *node, void *data) { // make arguments var in thie front of stack; if (is_class_func) { - block_->AddVariable("this", block_->NextRegisterId()); + long arg = block_->NextRegisterId(); + block_->AddVariable("this", arg); func_->func_state()->argc()++; + func_->func_state()->args().push_back(arg); } for (int i = 0; i < proto->GetArgs().size(); i++) { - std::string arg = proto->GetArgs().at(i); - block_->AddVariable(arg, block_->NextRegisterId()); + long arg = block_->NextRegisterId(); + block_->AddVariable(proto->GetArgs().at(i), arg); + func_->func_state()->args().push_back(arg); func_->func_state()->argc()++; } node->body()->Accept(this, nullptr); + if (func_->func_state()->out_closure().size() > 0) { + for (int i = 0; i < func_->func_state()->out_closure().size(); i++) { + ValueRef *ref = func_->func_state()->out_closure()[i]; + func_->func_state()->AddInstruction(CREATE_Ax(OP_REMOVE_CLOSURE, ref->ref_id())); + } + } } // function prototype @@ -478,7 +533,7 @@ void CodeGenerator::Visit(ThisExpression *node, void *data) { long rhs = block_->FindRegisterId("this"); if (rhs != ret) { // a = b - func_->func_state()->AddInstruction(CREATE_ABC(OP_MOVE, ret, rhs, 0)); + func_->func_state()->AddInstruction(CREATE_ABx(OP_MOVE, ret, rhs)); } } } @@ -506,22 +561,26 @@ void CodeGenerator::Visit(ArrowFunctionStatement *node, void *data) { block_->NextRegisterId(); // make arguments var in thie front of stack; if (is_class_func) { - block_->AddVariable("this", block_->NextRegisterId()); + long arg = block_->NextRegisterId(); + block_->AddVariable("this", arg); func_->func_state()->argc()++; + func_->func_state()->args().push_back(arg); } // make arguments var in thie front of stack; for (int i = 0; i < node->args().size(); i++) { if (node->args()[i]->IsIdentifier()) { - std::string arg = node->args()[i]->AsIdentifier()->GetName(); - block_->AddVariable(arg, block_->NextRegisterId()); + long arg = block_->NextRegisterId(); + block_->AddVariable(node->args()[i]->AsIdentifier()->GetName(), arg); func_->func_state()->argc()++; + func_->func_state()->args().push_back(arg); } else if (node->args()[i]->IsCommaExpression()) { Handle arg_list = node->args()[i]->AsCommaExpression()->exprs(); for (int j = 0; j < arg_list->Size(); j++) { - std::string arg = arg_list->raw_list()[j]->AsIdentifier()->GetName(); - block_->AddVariable(arg, block_->NextRegisterId()); + long arg = block_->NextRegisterId(); + block_->AddVariable(arg_list->raw_list()[j]->AsIdentifier()->GetName(), arg); func_->func_state()->argc()++; + func_->func_state()->args().push_back(arg); } } else { @@ -532,11 +591,17 @@ void CodeGenerator::Visit(ArrowFunctionStatement *node, void *data) { if (node->body()->IsJSXNodeExpression()) { long return1 = block_->NextRegisterId(); node->body()->Accept(this, &return1); - func_->func_state()->AddInstruction(CREATE_ABC(OP_RETURN1, return1, 0, 0)); + func_->func_state()->AddInstruction(CREATE_Ax(OP_RETURN1, return1)); } else { node->body()->Accept(this, nullptr); } + if (func_->func_state()->out_closure().size() > 0) { + for (int i = 0; i < func_->func_state()->out_closure().size(); i++) { + ValueRef *ref = func_->func_state()->out_closure()[i]; + func_->func_state()->AddInstruction(CREATE_Ax(OP_REMOVE_CLOSURE, ref->ref_id())); + } + } } // associate function_name and function_state if (func_->parent() == nullptr) { @@ -589,6 +654,7 @@ void CodeGenerator::Visit(ClassStatement *node, void *data) { class_value = exec_state_->class_factory()->CreateClassDescriptor(super_value ? ValueTo(super_value) : nullptr); exec_state_->global()->Add(class_name, class_value); ClassScope scope(this, &class_value); + class_->class_name() = class_name; node->Body()->Accept(this, nullptr); } while (0); @@ -605,29 +671,39 @@ void CodeGenerator::Visit(NewExpression *node, void *data) { RegisterScope scope(block_); long lhs = data == nullptr ? block_->NextRegisterId() : *static_cast(data); if (lhs >= 0) { - FuncState *state = func_->func_state(); - long rhs = block_->FindRegisterId(node->member()->AsIdentifier()->GetName()); - if (rhs >= 0) { - if (node->is_class()) { - state->AddInstruction(CREATE_ABC(OP_NEW, lhs, Value::CLASS_DESC, rhs)); + FuncState *func_state = func_->func_state(); + long rhs = block_->FindRegisterId(node->name()->AsIdentifier()->GetName()); + if (rhs < 0) { + int index = exec_state_->global()->IndexOf(node->name()->AsIdentifier()->GetName()); + if (index >= 0) { + Value *name = exec_state_->global()->Find(index); + if (IsClass(name)) { + rhs = block_->NextRegisterId(); + func_state->AddInstruction(CREATE_ABx(OP_GETGLOBAL, rhs, index)); + } + else { + // function call + func_state->AddInstruction(CREATE_ABx(OP_GETGLOBAL, lhs, index)); + break; + } } else { - state->AddInstruction(CREATE_ABC(OP_MOVE, lhs, rhs, 0)); + throw GeneratorError("can't find new identifier: " + node->name()->AsIdentifier()->GetName()); } - break; } - int index = exec_state_->global()->IndexOf(node->member()->AsIdentifier()->GetName()); - if (index >= 0) { - Value *value = exec_state_->global()->Find(index); - if (IsClass(value)) { - rhs = block_->NextRegisterId(); - state->AddInstruction(CREATE_ABx(OP_GETGLOBAL, rhs, index)); - state->AddInstruction(CREATE_ABC(OP_NEW, lhs, Value::CLASS_DESC, rhs)); - } - else { - state->AddInstruction(CREATE_ABx(OP_GETGLOBAL, lhs, index)); + func_state->AddInstruction(CREATE_ABC(OP_NEW, lhs, Value::CLASS_DESC, rhs)); + long caller = block_->NextRegisterId(); + long inst = block_->NextRegisterId(); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, inst, lhs)); + std::vector orders = { caller, inst }; + if (node->args()->Size() > 0) { + for (int i = 0; i < node->args()->Size(); i++) { + long arg = block_->NextRegisterId(); + orders.push_back(arg); + node->args()->raw_list()[i]->Accept(this, &arg); } } + AddCallInstruction(lhs, OP_CONSTRUCTOR, orders); } } while (0); @@ -667,14 +743,14 @@ void CodeGenerator::Visit(JSXNodeExpression *node, void *data) { throw GeneratorError("can't find identifier appendChild"); } func_state->AddInstruction(CREATE_ABx(OP_GETGLOBAL, caller, index)); - func_state->AddInstruction(CREATE_ABC(OP_MOVE, arg_0, reg_parent, 0)); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, arg_0, reg_parent)); childrens[i]->Accept(this, &arg_1); func_state->AddInstruction(CREATE_ABC(OP_CALL, ret, argc, caller)); } } if (data) { long ret = *static_cast(data); - func_state->AddInstruction(CREATE_ABC(OP_MOVE, ret, reg_parent, 0)); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, ret, reg_parent)); } } while (0); @@ -700,94 +776,170 @@ void CodeGenerator::Visit(BinaryExpression *node, void *data) { int for_start_index = (int)func_state->instructions().size(); // aka next one. block_->set_for_start_index(for_start_index); } - long right = block_->NextRegisterId(); - if (node->rhs().get() != NULL) { - node->rhs()->Accept(this, &right); - } switch (opeartion) { case BinaryOperation::kAddition: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } // a + b func_state->AddInstruction(CREATE_ABC(OP_ADD, ret, left, right)); break; } case BinaryOperation::kSubtraction: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } // a - b func_state->AddInstruction(CREATE_ABC(OP_SUB, ret, left, right)); break; } case BinaryOperation::kMultiplication: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } // a * b func_state->AddInstruction(CREATE_ABC(OP_MUL, ret, left, right)); break; } case BinaryOperation::kDivision: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } // a / b func_state->AddInstruction(CREATE_ABC(OP_DIV, ret, left, right)); break; } case BinaryOperation::kMod: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } // a % b func_state->AddInstruction(CREATE_ABC(OP_MOD, ret, left, right)); break; } case BinaryOperation::kLessThan: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_LT, ret, left, right)); break; } case BinaryOperation::kGreaterThan: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_GT, ret, left, right)); break; } case BinaryOperation::kLessThanEqual: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_LTE, ret, left, right)); break; } case BinaryOperation::kGreaterThanEqual: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_GTE, ret, left, right)); break; } case BinaryOperation::kAnd: { + auto slot = func_state->AddInstruction(0); + int second_index = (int)func_state->instructions().size() - 1; + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_AND, ret, left, right)); + auto goto_slot = func_state->AddInstruction(0); + int third_index = (int)func_state->instructions().size() - 1; + func_state->AddInstruction(CREATE_ABx(OP_MOVE, ret, left)); + int end_index = (int)func_state->instructions().size(); + func_state->ReplaceInstruction(slot, CREATE_ABx(OP_JMP, left, third_index - second_index)); + func_state->ReplaceInstruction(goto_slot, CREATE_Ax(OP_GOTO, end_index)); break; } case BinaryOperation::kStrictEqual: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_SEQ, ret, left, right)); break; } case BinaryOperation::kIn: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_IN, ret, left, right)); break; } case BinaryOperation::kOr: { + auto slot = func_state->AddInstruction(0); + int second_index = (int)func_state->instructions().size() - 1; + func_state->AddInstruction(CREATE_ABx(OP_MOVE, ret, left)); + auto goto_slot = func_state->AddInstruction(0); + int third_index = (int)func_state->instructions().size() - 1; + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_OR, ret, left, right)); + int end_index = (int)func_state->instructions().size(); + func_state->ReplaceInstruction(slot, CREATE_ABx(OP_JMP, left, third_index - second_index)); + func_state->ReplaceInstruction(goto_slot, CREATE_Ax(OP_GOTO, end_index)); break; } case BinaryOperation::kEqual: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_EQ, ret, left, right)); break; } case BinaryOperation::kNotEqual: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_EQ, ret, left, right)); func_state->AddInstruction(CREATE_ABx(OP_NOT, ret, ret)); break; } case BinaryOperation::kStrictNotEqual: { + long right = block_->NextRegisterId(); + if (node->rhs().get() != NULL) { + node->rhs()->Accept(this, &right); + } func_state->AddInstruction(CREATE_ABC(OP_SEQ, ret, left, right)); func_state->AddInstruction(CREATE_ABx(OP_NOT, ret, ret)); break; @@ -826,10 +978,10 @@ void CodeGenerator::Visit(AssignExpression *node, void *data) { case AssignOperation::kAssign: { if (class_ && node->lhs()->IsMemberExpression() && node->lhs()->AsMemberExpression()->expr()->IsThisExpression()) { - func_state->AddInstruction(CREATE_ABC(OP_SETMEMBERVAR, left, right, 0)); + func_state->AddInstruction(CREATE_ABx(OP_SETMEMBERVAR, left, right)); } else { - func_state->AddInstruction(CREATE_ABC(OP_MOVE, left, right, 0)); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, left, right)); } break; } @@ -837,14 +989,14 @@ void CodeGenerator::Visit(AssignExpression *node, void *data) { { long ret = block_->NextRegisterId(); func_state->AddInstruction(CREATE_ABC(OP_ADD, ret, left, right)); - func_state->AddInstruction(CREATE_ABC(OP_MOVE, left, ret, 0)); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, left, ret)); break; } case AssignOperation::kAssignSub: { long ret = block_->NextRegisterId(); func_state->AddInstruction(CREATE_ABC(OP_SUB, ret, left, right)); - func_state->AddInstruction(CREATE_ABC(OP_MOVE, left, ret, 0)); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, left, ret)); break; } default: @@ -860,7 +1012,7 @@ void CodeGenerator::Visit(Declaration *node, void *data) { node->expr()->Accept(this, ®); } else { - func_state->AddInstruction(CREATE_ABC(OP_LOADNULL, reg, 0, 0)); + func_state->AddInstruction(CREATE_Ax(OP_LOADNULL, reg)); } } @@ -888,7 +1040,7 @@ void CodeGenerator::Visit(IntegralConstant* node, void* data) { FuncState* func_state = func_->func_state(); int value = node->value(); int index = func_state->AddConstant(static_cast(value)); - Instruction i = CREATE_ABx(OpCode::OP_LOADK, reg, index); + Instruction i = CREATE_ABx(OP_LOADK, reg, index); func_state->AddInstruction(i); } } @@ -899,7 +1051,7 @@ void CodeGenerator::Visit(BooleanConstant* node, void* data) { FuncState* func_state = func_->func_state(); bool value = node->pred(); int index = func_state->AddConstant(static_cast(value)); - Instruction i = CREATE_ABx(OpCode::OP_LOADK, reg, index); + Instruction i = CREATE_ABx(OP_LOADK, reg, index); func_state->AddInstruction(i); } } @@ -910,7 +1062,7 @@ void CodeGenerator::Visit(DoubleConstant* node, void* data) { FuncState* func_state = func_->func_state(); double value = node->value(); int index = func_state->AddConstant(static_cast(value)); - Instruction i = CREATE_ABx(OpCode::OP_LOADK, reg, index); + Instruction i = CREATE_ABx(OP_LOADK, reg, index); func_state->AddInstruction(i); } } @@ -919,7 +1071,7 @@ void CodeGenerator::Visit(NullConstant *node, void *data) { long reg = data == nullptr ? -1 : *static_cast(data); if (reg >= 0) { FuncState *func_state = func_->func_state(); - func_state->AddInstruction(CREATE_ABC(OP_LOADNULL, reg, 0, 0)); + func_state->AddInstruction(CREATE_Ax(OP_LOADNULL, reg)); } } @@ -927,7 +1079,7 @@ void CodeGenerator::Visit(UndefinedConstant *node, void *data) { long reg = data == nullptr ? -1 : *static_cast(data); if (reg >= 0) { FuncState *func_state = func_->func_state(); - func_state->AddInstruction(CREATE_ABC(OP_LOADNULL, reg, 0, 0)); + func_state->AddInstruction(CREATE_Ax(OP_LOADNULL, reg)); } } @@ -1003,6 +1155,36 @@ void CodeGenerator::Visit(ArrayConstant *node, void *data) { } } } + +void CodeGenerator::Visit(ClassProperty *node, void *data) { + RegisterScope scope(block_); + assert(class_); + do { + FuncState *func_state = func_->func_state(); + if (node->is_static()) { + long lhs = block_->NextRegisterId(); + long rhs = block_->NextRegisterId(); + int index = exec_state_->global()->IndexOf(class_->class_name()); + if (index <= 0) { + throw GeneratorError("can't find class name " + class_->class_name()); + break; + } + func_state->AddInstruction(CREATE_ABx(OP_GETGLOBAL, lhs, index)); + auto constant = exec_state_->string_table_->StringFromUTF8(node->name()); + index = func_state->AddConstant(std::move(constant)); + func_state->AddInstruction(CREATE_ABx(OP_LOADK, rhs, index)); + func_state->AddInstruction(CREATE_ABC(OP_GETMEMBERVAR, lhs, lhs, rhs)); + if (node->init()) { + node->init()->Accept(this, &rhs); + func_state->AddInstruction(CREATE_ABx(OP_MOVE, lhs, rhs)); + } + else { + func_state->AddInstruction(CREATE_Ax(OP_LOADNULL, lhs)); + } + } + + } while (0); +} void CodeGenerator::Visit(MemberExpression *node, void *data) { RegisterScope registerScope(block_); @@ -1059,7 +1241,7 @@ void CodeGenerator::Visit(Identifier *node, void *data) { FuncState *state = func_->func_state(); long reg_b = block_->FindRegisterId(node->GetName()); if (reg_b >= 0) { - state->AddInstruction(CREATE_ABC(OP_MOVE, reg_a, reg_b, 0)); + state->AddInstruction(CREATE_ABx(OP_MOVE, reg_a, reg_b)); return; } @@ -1081,12 +1263,12 @@ void CodeGenerator::Visit(Identifier *node, void *data) { int tableIndex = func_state->AddConstant(std::move(value)); func_state->AddInstruction( - CREATE_ABx(OpCode::OP_LOADK, right, tableIndex)); + CREATE_ABx(OP_LOADK, right, tableIndex)); func_state->AddInstruction( CREATE_ABC(OP_GETMEMBER, reg_a, this_idx, right)); } else { // make data undefined. - state->AddInstruction(CREATE_ABC(OP_LOADNULL, reg_a, 0, 0)); + state->AddInstruction(CREATE_Ax(OP_LOADNULL, reg_a)); } } } @@ -1107,17 +1289,20 @@ void CodeGenerator::Visit(PrefixExpression *node, void *data) { PrefixOperation operation = node->op(); // ++i if (operation == PrefixOperation::kIncrement) { - func_->func_state()->AddInstruction(CREATE_ABC(OP_PRE_INCR, reg, ret, 0)); + func_->func_state()->AddInstruction(CREATE_ABx(OP_PREV_INCR, reg, ret)); } // --i else if (operation == PrefixOperation::kDecrement) { - func_->func_state()->AddInstruction(CREATE_ABC(OP_PRE_DECR, reg, ret, 0)); + func_->func_state()->AddInstruction(CREATE_ABx(OP_PREV_DECR, reg, ret)); } else if (operation == PrefixOperation::kNot) { func_->func_state()->AddInstruction(CREATE_ABx(OP_NOT, ret, reg)); } else if (operation == PrefixOperation::kUnfold) { - func_->func_state()->AddInstruction(CREATE_ABC(OP_MOVE, ret, reg, 0)); + func_->func_state()->AddInstruction(CREATE_ABx(OP_MOVE, ret, reg)); + } + else if (operation == PrefixOperation::kTypeof) { + func_->func_state()->AddInstruction(CREATE_ABx(OP_TYPEOF, ret, reg)); } } @@ -1137,23 +1322,111 @@ void CodeGenerator::Visit(PostfixExpression *node, void *data) { PostfixOperation operation = node->op(); // i++ if (operation == PostfixOperation::kIncrement) { - func_->func_state()->AddInstruction(CREATE_ABC(OP_POST_INCR, reg, ret, 0)); + func_->func_state()->AddInstruction(CREATE_ABx(OP_POST_INCR, reg, ret)); } // i++ else if (operation == PostfixOperation::kDecrement) { - func_->func_state()->AddInstruction(CREATE_ABC(OP_POST_DECR, reg, ret, 0)); + func_->func_state()->AddInstruction(CREATE_ABx(OP_POST_DECR, reg, ret)); } } void CodeGenerator::Visit(ReturnStatement *node, void *data) { FuncState *func_state = func_->func_state(); if (node->expr() == nullptr) { - func_state->AddInstruction(CREATE_ABC(OP_RETURN0, 0, 0, 0)); + func_state->AddInstruction(CREATE_Ax(OP_RETURN0, 0)); } else { long ret = block_->NextRegisterId(); node->expr()->Accept(this, &ret); - func_state->AddInstruction(CREATE_ABC(OP_RETURN1, ret, 0, 0)); + func_state->AddInstruction(CREATE_Ax(OP_RETURN1, ret)); + } +} + +void CodeGenerator::Visit(SwitchStatement* node, void* data) { + BlockScope for_scope(this); + block_->set_is_switch(true); + + long test_value_id = block_->NextRegisterId(); + long case_value_id = block_->NextRegisterId(); + long test_result_id = block_->NextRegisterId(); + + FuncState *func_state = func_->func_state(); + auto &cases = node->get_cases(); + //load test value into [test_value_id] + node->test_case()->Accept(this,&test_value_id); + std::vector switch_case_index; + std::vector jump_slots; + + //value test for cases + int defaultIndex = -1; + Handle defaultCase; + int index = 0; + for(auto& a_case: cases){ + //load case value into [case_value_id] + const Handle& caseStatement = a_case->AsCaseStatement(); + if (caseStatement->is_default()){ + jump_slots.push_back(0); + defaultCase = caseStatement; + defaultIndex = index; + continue; + } + caseStatement->test_case()->Accept(this, &case_value_id); + func_state->AddInstruction(CREATE_ABC(OP_EQ, test_result_id, test_value_id, case_value_id)); + size_t jump_slot = func_state->AddInstruction(0); + jump_slots.push_back(jump_slot); + index++; + } + + size_t skip_to_end_slot = 0; + if (defaultIndex != -1){ + //has default case + size_t defaultJump = func_state->AddInstruction(0); + jump_slots[defaultIndex] = defaultJump; + } else { + //no default + skip_to_end_slot = func_state->AddInstruction(0); + } + + //expression list for cases + for(auto& a_case: cases){ + size_t lable_index = func_state->instructions().size(); + switch_case_index.push_back(lable_index); + + a_case->AsCaseStatement()->statements()->Accept(this, nullptr); + } + + //replace case jump; + index = 0; + for(size_t to_replace:jump_slots){ + if(index == defaultIndex){ + func_state->ReplaceInstruction(to_replace,CREATE_Ax(OP_GOTO,switch_case_index[index])); + } else { + func_state->ReplaceInstruction(to_replace,CREATE_ABx(OP_TRUE_JMPTO,test_result_id,switch_case_index[index])); + } + index++; + } + + //replace break; + size_t end_index = func_state->instructions().size();; + for(auto& to_replace:block_->break_slots()){ + func_state->ReplaceInstruction(to_replace, CREATE_Ax(OP_GOTO,end_index)); + } + + if (defaultIndex == -1){ + //no default, replace skip instruction; + func_state->ReplaceInstruction(skip_to_end_slot, CREATE_Ax(OP_GOTO,end_index)); + } +} + +void CodeGenerator::Visit(BreakStatement* node, void* data) { + auto slot = func_->func_state()->AddInstruction(0); + block_->break_slots().push_back(slot); +} + +void CodeGenerator::Visit(TryCatchStatement* node, void* data) { + node->try_block()->Accept(this, nullptr); + if(node->finally()!= nullptr){ + node->finally()->Accept(this, nullptr); } } @@ -1187,7 +1460,7 @@ CodeGenerator::RegisterScope::~RegisterScope() while (iter != block->reg_refs().end()) { long reg_ref = *iter; if (reg_ref >= start_idx) { - func_state->AddInstruction(CREATE_ABC(OP_RESETOUTVAR, reg_ref, 0, 0)); + func_state->AddInstruction(CREATE_Ax(OP_RESETOUTVAR, reg_ref)); iter = block->reg_refs().erase(iter); } else { @@ -1244,15 +1517,13 @@ std::vector& CodeGenerator::BlockCnt::for_continue_slots() { } return for_continue_slots_; } - -std::vector& CodeGenerator::BlockCnt::for_break_slots() { - if (is_loop()) { + +std::vector& CodeGenerator::BlockCnt::break_slots() { + if (is_loop()||is_switch()) { return for_break_slots_; } if (parent() != nullptr) { - if (parent()->is_loop()) { - return parent()->for_break_slots_; - } + return parent()->break_slots(); } return for_break_slots_; } @@ -1272,7 +1543,7 @@ int CodeGenerator::BlockCnt::for_update_index() { void CodeGenerator::BlockCnt::reset() { for (int i = 0; i < reg_refs_.size(); i++) { if (func_state()) { - func_state()->AddInstruction(CREATE_ABC(OP_RESETOUTVAR, reg_refs_[i], 0, 0)); + func_state()->AddInstruction(CREATE_Ax(OP_RESETOUTVAR, reg_refs_[i])); } } } @@ -1301,7 +1572,13 @@ long CodeGenerator::BlockCnt::FindRegisterId(const std::string &name) { } reg_ref = root_block->NextRegisterId(); root_block->reg_refs().push_back(reg_ref); - func_state_->AddInstruction(CREATE_ABx(OP_GETOUTVAR, reg_ref, ref->ref_id())); + if (ref->is_closure()) { + func_state_->AddInClosure(ref); + func_state_->AddInstruction(CREATE_ABx(OP_IN_CLOSURE, reg_ref, ref->ref_id())); + } + else { + func_state_->AddInstruction(CREATE_ABx(OP_GETOUTVAR, reg_ref, ref->ref_id())); + } } return reg_ref; } @@ -1312,14 +1589,19 @@ long CodeGenerator::BlockCnt::FindRegisterId(const std::string &name) { ValueRef *CodeGenerator::BlockCnt::FindValueRef(const std::string &name, long ®_ref) { auto iter = variables_.find(name); if (iter != variables_.end()) { - if (exec_state_ && func_state_) { + if (exec_state_ && func_state_ ) { ValueRef *ref = exec_state_->AddRef(func_state_, iter->second); + bool is_closure = func_state_->Inclusive(iter->second); + if (is_closure) { + ref->is_closure() = is_closure; + func_state_->AddOutClosure(ref); + } Instruction instruction = func_state_->instructions().size() > 0 ? func_state_->instructions()[func_state_->instructions().size() - 1] : 0; - OpCode op(GET_OP_CODE(instruction)); + OPCode op(GET_OP_CODE(instruction)); if (instruction && (op == OP_RETURN0 || op == OP_RETURN1)) { func_state_->instructions().pop_back(); } - func_state_->AddInstruction(CREATE_ABx(OP_SETOUTVAR, iter->second, ref->ref_id())); + func_state_->AddInstruction(CREATE_ABx(is_closure ? OP_OUT_CLOSURE : OP_SETOUTVAR, iter->second, ref->ref_id())); if (instruction && (op == OP_RETURN0 || op == OP_RETURN1)) { func_state_->AddInstruction(instruction); } diff --git a/weex_core/Source/core/data_render/code_generator.h b/weex_core/Source/core/data_render/code_generator.h index b1a9aaa407..89ebfe97dc 100644 --- a/weex_core/Source/core/data_render/code_generator.h +++ b/weex_core/Source/core/data_render/code_generator.h @@ -40,6 +40,7 @@ class CodeGenerator : public ASTVisitor { ~CodeGenerator() {} void Visit(ChunkStatement *node, void *data) override; void Visit(StringConstant *node, void *data) override; + void Visit(RegexConstant *node, void *data) override; void Visit(CallExpression *node, void *data) override; void Visit(ArgumentList *node, void *data) override; void Visit(IfStatement *node, void *data) override; @@ -74,6 +75,10 @@ class CodeGenerator : public ASTVisitor { void Visit(NewExpression *node, void *data) override; void Visit(PostfixExpression *node, void *data) override; void Visit(ContinueStatement *node, void *data) override; + void Visit(SwitchStatement *node, void *data) override; + void Visit(TryCatchStatement *node, void *data) override; + void Visit(BreakStatement *node, void *data) override; + void Visit(ClassProperty *node, void *data) override; private: template @@ -115,7 +120,7 @@ class CodeGenerator : public ASTVisitor { int for_start_index(); int for_update_index(); std::vector& for_continue_slots(); - std::vector& for_break_slots(); + std::vector& break_slots(); void set_for_start_index(int index) { for_start_index_ = index; } void set_for_update_index(int index) { for_update_index_ = index; } inline std::unordered_map &variables() { @@ -125,6 +130,8 @@ class CodeGenerator : public ASTVisitor { inline int idx() { return idx_; } inline bool is_loop() { return is_loop_; } inline void set_is_loop(bool is_loop) { is_loop_ = is_loop; } + inline bool is_switch() { return is_switch_; } + inline void set_is_switch(bool flag) { is_switch_ = flag; } inline std::vector& reg_refs() { return reg_refs_; } inline bool& is_register_scope() { return is_register_scope_; } void reset(); @@ -135,6 +142,7 @@ class CodeGenerator : public ASTVisitor { std::vector reg_refs_; int idx_; bool is_loop_; + bool is_switch_; bool is_register_scope_; FuncState *func_state_{nullptr}; ExecState *exec_state_{nullptr}; @@ -169,14 +177,16 @@ class CodeGenerator : public ASTVisitor { class ClassCnt : public Node { public: - ClassCnt() {} - ~ClassCnt() {} - inline void set_class_value(Value *class_value) { - class_value_ = class_value; - } - inline Value *class_value() { return class_value_; } + ClassCnt() {} + ~ClassCnt() {} + inline void set_class_value(Value *class_value) { + class_value_ = class_value; + } + inline Value *class_value() { return class_value_; } + inline std::string &class_name() { return class_name_; } private: Value *class_value_; + std::string class_name_; }; class RegisterScope { public: @@ -218,6 +228,7 @@ class CodeGenerator : public ASTVisitor { CodeGenerator *cg_; DISALLOW_COPY_AND_ASSIGN(ClassScope); }; + void AddCallInstruction(long ret, OPCode code, std::vector orders); void EnterClass(Value *class_value); void LeaveClass(); void EnterFunction(); diff --git a/weex_core/Source/core/data_render/common_error.h b/weex_core/Source/core/data_render/common_error.h index 93b4e55be4..0232cf3df6 100644 --- a/weex_core/Source/core/data_render/common_error.h +++ b/weex_core/Source/core/data_render/common_error.h @@ -25,6 +25,7 @@ #include #include "core/data_render/token.h" +#include "base/string_util.h" namespace weex { namespace core { @@ -55,13 +56,19 @@ class GeneratorError : public Error { class JSError : public Error { public: JSError(std::string prefix, std::string str) - : Error("[JSError]" + prefix, std::move(str)) { } + : Error("[JSError]=>" + prefix, std::move(str)) { } }; class VMExecError : public Error { public: VMExecError(std::string str) - : Error("[VMExecError]", std::move(str)) { } + : Error("[VMExecError]=>", std::move(str)) { } +}; + +class EncoderError : public Error { +public: + EncoderError(std::string str) + : Error("[EncoderError]=>", std::move(str)) { } }; class OpcodeDecodeError : public Error { @@ -70,11 +77,16 @@ class OpcodeDecodeError : public Error { : Error("[OpcodeDecodeError]", std::move(str)) { } }; +class DecoderError : public Error { +public: + DecoderError(std::string str) + : Error("[DecoderError]=>", std::move(str)) { } +}; + class SyntaxError : public JSError { public: SyntaxError(Token token, std::string str = "") - : JSError("SyntaxError", std::move(str)), token_(token) - { } + : JSError("SyntaxError(" + base::to_string(token.position().row() + 1) + ":" + base::to_string(token.position().col()) + ") '" + token.view() + "'", std::move(str)), token_(token) { } const char *what() const noexcept override { @@ -120,15 +132,6 @@ class RangeError : public JSError { { } }; -template - -std::string to_string(T value) -{ - std::ostringstream os ; - os << value ; - return os.str() ; -} - } } } diff --git a/weex_core/Source/core/data_render/exec_state.cc b/weex_core/Source/core/data_render/exec_state.cc index 587078fb09..56aae72010 100644 --- a/weex_core/Source/core/data_render/exec_state.cc +++ b/weex_core/Source/core/data_render/exec_state.cc @@ -26,9 +26,8 @@ #include "core/data_render/rax_parser.h" #include "core/data_render/rax_parser_context.h" #include "core/data_render/common_error.h" -#include "core/data_render/binary_file.h" #include "core/data_render/class_array.h" - +#include "core/data_render/vnode/vnode_exec_env.h" #if DEBUG #include "core/data_render/monitor/vm_monitor.h" #endif @@ -38,6 +37,20 @@ namespace core { namespace data_render { int ValueRef::gs_ref_id = 0; + +FuncClosure::FuncClosure(ValueRef *ref) { + if (ref) { + func_state_ = ref->func_state(); + register_id_ = ref->register_id(); + value_ = ref->value(); + value_.ref = &ref->value(); + } + else { + SetNil(&value_); + value_.ref = nullptr; + } + ref_ = ref; +} void ExecStack::reset() { size_t size = (VM_EXEC_STACK_SIZE - (top_ - base()) - 1) * sizeof(Value); @@ -56,16 +69,29 @@ ExecState::ExecState(VM *vm) render_context_(new VNodeRenderContext), class_factory_(new ClassFactory()), global_variables_() {} - + +ExecState::~ExecState() { + for (ValueRef *ref : refs_) { + if (ref) { + delete ref; + } + } +} + void ExecState::Compile(std::string& err) { - #if DEBUG TimeCost tc("Compile"); #endif + ValueRef::reset(); + class_compile_index_ = static_cast(class_factory_->descs().size()); + global_compile_index_ = static_cast(global()->size()); + string_compile_index_ = static_cast(string_table_->store().size()); ValueRef::gs_ref_id = 0; err.clear(); CodeGenerator generator(this); if (!context()->raw_json().is_null()) { + VNodeExecEnv::ParseData(this); + VNodeExecEnv::ParseStyle((this)); ParseResult result = Parser::Parse(context()->raw_json(),err); generator.Visit(result.expr().get(), nullptr); } @@ -123,853 +149,6 @@ void ExecState::Execute(std::string& err) { } } -void ExecState::startEncode() { - BinaryFile* file = BinaryFile::instance(); - - int magic_number = 0x6d736100; - unsigned version = 1; - file->write((char*)&magic_number, sizeof(int32_t)); - file->write((char*)&version, sizeof(u_int32_t)); - - encodeStringSection(); - encodeTableSection(); - encodeFunctionSection(); - encodeStartSection(); - encodeGlobalSection(); - encodeGlobalVariableSection(); - encodeStyleSection(); - encodeArraySection(); - encodeRefSection(); - encodeClassSection(); -} - -void ExecState::encodeStringSection() { - unsigned id = Section::STRING_SECTION; //string_section - - const std::vector>>& store = string_table_->store(); - unsigned size = static_cast(store.size()); - BinaryFile* file = BinaryFile::instance(); - - file->write((char*)&id, sizeof(u_int32_t)); - file->write((char*)&size, sizeof(u_int32_t)); - for (auto &mapString : store) { - unsigned length = static_cast(mapString.first.length()) + 1; - file->write(mapString.first.c_str(), static_cast(sizeof(char) * length)); - } -} - -void ExecState::encodeArraySection() { - unsigned id = Section::ARRAY_SECTION; - std::vector arrays = class_factory_->arrays(); - unsigned size = static_cast(arrays.size()); - BinaryFile* file = BinaryFile::instance(); - - file->write((char*)&id, sizeof(u_int32_t)); - file->write((char*)&size, sizeof(u_int32_t)); - for (auto array : arrays) { - unsigned itemSize = static_cast(array->items.size()); - file->write((char*)&itemSize, sizeof(u_int32_t)); - for (auto &value : array->items) { - encodeValue(value); - } - } -} - -void ExecState::encodeTableSection() { - unsigned id = Section::TABLE_SECTION; - std::vector
tables = class_factory_->tables(); - - unsigned size = static_cast(tables.size()); - BinaryFile* file = BinaryFile::instance(); - - file->write((char*)&id, sizeof(u_int32_t)); - file->write((char*)&size, sizeof(u_int32_t)); - - for (auto table : tables) { - unsigned mapSize = static_cast(table->map.size()); - file->write((char*)&mapSize, sizeof(u_int32_t)); - for (auto &map : table->map) { - std::string name = map.first; - Value value = map.second; - String str(name); - unsigned length = static_cast(str.length()) + 1; - file->write(str.c_str(), static_cast(sizeof(char) * length)); - encodeValue(value); - } - } -} - -void ExecState::encodeFunctionSection() { - BinaryFile* file = BinaryFile::instance(); - unsigned id = Section::FUNCTION_SECTION; - - FuncState* func_state_base = func_state_.get(); - std::vector children = func_state_base->getAllChildren(); - std::vector func_states; - func_states.push_back(func_state_base); - for (auto &func : children) { - func_states.push_back(func); - } - unsigned size = static_cast(func_states.size()); - file->write((char*)&id, sizeof(u_int32_t)); - file->write((char*)&size, sizeof(u_int32_t)); - - for (auto &func_state : func_states) { - auto it = std::find(func_states.begin(), func_states.end(), func_state->super_func()); - int super_index = -1; - if (it != func_states.end()) { - super_index = static_cast(it - func_states.begin()); - } - file->write((char*)&super_index, sizeof(int32_t)); - - bool is_class_func = func_state->is_class_func(); - file->write((char*)&is_class_func, sizeof(int8_t)); - - int argc = func_state->argc(); - file->write((char*)&argc, sizeof(int32_t)); - - unsigned opcodeSize = static_cast(func_state->instructions().size()); - file->write((char*)&opcodeSize, sizeof(u_int32_t)); - for (int i=0; i(func_state->instructions()[i]); - file->write((char*)&opcode, sizeof(u_int32_t)); - } - - unsigned constantSize = static_cast(func_state->GetConstantSize()); - file->write((char*)&constantSize, sizeof(u_int32_t)); - for (int i=0; iGetConstant(i))); - } - } -} - -void ExecState::encodeStartSection() { - BinaryFile* file = BinaryFile::instance(); - unsigned id = Section::START_SECTION; - unsigned index = 0; - file->write((char*)&id, sizeof(u_int32_t)); - file->write((char*)&index, sizeof(u_int32_t)); -} - -void ExecState::encodeGlobalSection() { - BinaryFile* file = BinaryFile::instance(); - unsigned id = Section::GLOBAL_SECTION; - unsigned size = static_cast(global_->size()) - global_->register_size(); - - file->write((char*)&id, sizeof(u_int32_t)); - file->write((char*)&size, sizeof(u_int32_t)); - int init_data_index = global_->IndexOf("_init_data"); - int weex_data_index = global_->IndexOf("__weex_data__"); - file->write((char*)&init_data_index, sizeof(int32_t)); - file->write((char*)&weex_data_index, sizeof(int32_t)); - - for (int i=global_->register_size(); isize(); i++) { - Value* value = global_->Find(i); - encodeValue(*value); - } -} - -void ExecState::encodeGlobalVariableSection() { - BinaryFile* file = BinaryFile::instance(); - unsigned id = Section::GLOBAL_VARIABLE_SECTION; - unsigned size = static_cast(global_variables_.size()); - - file->write((char*)&id, sizeof(u_int32_t)); - file->write((char*)&size, sizeof(u_int32_t)); - for (auto variable : global_variables_) { - unsigned length = static_cast(variable.first.length()) + 1; - file->write(variable.first.c_str(), static_cast(sizeof(char) * length)); - file->write((char*)&variable.second, sizeof(int64_t)); - } -} - -void ExecState::encodeStyleSection() { - unsigned id = Section::STYLE_SECTION; - std::map& styles = render_context_->style_json(); - - unsigned size = static_cast(styles.size()); - BinaryFile* file = BinaryFile::instance(); - - file->write((char*)&id, sizeof(u_int32_t)); - file->write((char*)&size, sizeof(u_int32_t)); - - for (auto style : styles) { - Value value(string_table()->StringFromUTF8(style.first)); - encodeValue(value); - const json11::Json::object& items = style.second.object_items(); - unsigned itemsSize = static_cast(items.size()); - file->write((char*)&itemsSize, sizeof(u_int32_t)); - for (auto it = items.begin(); it != items.end(); it++) { - unsigned length = static_cast(it->first.length()) + 1; - file->write(it->first.c_str(), static_cast(sizeof(char) * length)); - - unsigned strLen = static_cast(it->second.string_value().length()) + 1; - file->write(it->second.string_value().c_str(), static_cast(sizeof(char) * strLen)); - } - } -} - -void ExecState::encodeRefSection() { - unsigned id = Section::REF_SECTION; - unsigned size = static_cast(refs_.size()); - BinaryFile* file = BinaryFile::instance(); - - file->write((char*)&id, sizeof(u_int32_t)); - file->write((char*)&size, sizeof(u_int32_t)); - for (auto ref : refs_) { - Value value; - value.type = Value::Type::FUNC; - value.f = ref->func_state_; - encodeValue(value); - long register_id = ref->register_id(); - file->write((char*)®ister_id, sizeof(int64_t)); - encodeValue(ref->value_); - } -} - -void ExecState::encodeClassSection() { - unsigned id = Section::CLASS_SECTION; - std::vector descs = class_factory_->descs(); - - unsigned size = static_cast(descs.size()); - BinaryFile* file = BinaryFile::instance(); - - file->write((char*)&id, sizeof(u_int32_t)); - file->write((char*)&size, sizeof(u_int32_t)); - - int count = 0; - for (auto desc : descs) { - count++; - if (count <= 3) { - continue; - } - - int superIndex = class_factory_->findDesc(desc->p_super_); - file->write((char*)&superIndex, sizeof(int32_t)); - unsigned static_func_size = static_cast(desc->static_funcs_->size()); - file->write((char*)&static_func_size, sizeof(u_int32_t)); - for (int i=0; istatic_funcs_->Find(i); - encodeValue(*value); - - unsigned length = 0; - for (auto &item : desc->static_funcs_->map()) { - if (item.second == i) { - length = static_cast(item.first.length()) + 1; - file->write((char*)&length, sizeof(u_int32_t)); - file->write(item.first.c_str(), static_cast(sizeof(char) * length)); - break; - } - } - if (length == 0) { - file->write((char*)&length, sizeof(u_int32_t)); - } - } - - unsigned class_func_size = static_cast(desc->funcs_->size()); - file->write((char*)&class_func_size, sizeof(u_int32_t)); - for (int i=0; ifuncs_->Find(i); - encodeValue(*value); - - unsigned length = 0; - for (auto &item : desc->funcs_->map()) { - if (item.second == i) { - length = static_cast(item.first.length()) + 1; - file->write((char*)&length, sizeof(u_int32_t)); - file->write(item.first.c_str(), static_cast(sizeof(char) * length)); - break; - } - } - if (length == 0) { - file->write((char*)&length, sizeof(u_int32_t)); - } - } - } -} - -void ExecState::encodeValue(const Value &value) { - BinaryFile* file = BinaryFile::instance(); - file->write((char*)&value.type, sizeof(u_int32_t)); - - if (value.type == Value::Type::TABLE) { - std::vector
tables = class_factory_->tables(); - int payload = 0; - for (auto table : tables) { - if (value.gc == reinterpret_cast(table)) { - break; - } - payload++; - } - file->write((char*)&payload, sizeof(int32_t)); - } - - if (value.type == Value::Type::STRING) { - //int payload = static_cast(strings.size()); - int payload = 0; - for (auto &store : string_table_->store() ) { - if (value.str == store.second.get()) { - // printf("---- %s \n", str.get()->c_str()); - break; - } - payload++; - } - file->write((char*)&payload, sizeof(int32_t)); - } - - if (value.type == Value::Type::INT) { - file->write((char*)&value.i, sizeof(int64_t)); - } - - if (value.type == Value::Type::NUMBER) { - file->write((char*)&value.n, sizeof(double)); - } - - if (value.type == Value::Type::BOOL) { - file->write((char*)&value.b, sizeof(char)); - } - - if (value.type == Value::Type::FUNC) { - FuncState* func_state_base = func_state_.get(); - const std::vector &children = func_state_base->getAllChildren(); - std::vector func_states; - func_states.push_back(func_state_base); - for (auto &func : children) { - func_states.push_back(func); - } - - int payload = 0; - for (auto func_state : func_states) { - if (value.f == func_state) { - break; - } - payload++; - } - file->write((char*)&payload, sizeof(int32_t)); - } - - if (value.type == Value::Type::ARRAY) { - std::vector arrays = class_factory_->arrays(); - int payload = 0; - for (auto array : arrays ) { - if (value.gc == reinterpret_cast(array)) { - break; - } - payload++; - } - file->write((char*)&payload, sizeof(int32_t)); - } - - if (value.type == Value::Type::CLASS_DESC) { - int payload = 0; - std::vector descs = class_factory_->descs(); - for (auto desc : descs) { - if (value.gc == reinterpret_cast(desc)) { - break; - } - payload++; - } - file->write((char*)&payload, sizeof(int32_t)); - } -} - -void ExecState::endEncode() { - BinaryFile* file = BinaryFile::instance(); - file->writeFinish(); -} - -bool ExecState::startDecode() { - ValueRef::gs_ref_id = 0; - - BinaryFile* file = BinaryFile::instance(); - int magic_number; - file->read((char*)&magic_number, sizeof(int32_t)); - if (magic_number != 0x6d736100) { - throw OpcodeDecodeError("The format of file is not wasm"); - } - unsigned version; - file->read((char*)&version, sizeof(u_int32_t)); - if (version > 1) { - throw OpcodeDecodeError("The version of file can not support"); - } - - while (!file->eof()) { - Section section_id = NULL_SECTION; - file->read((char*)§ion_id, sizeof(u_int32_t)); - switch (section_id) { - case STRING_SECTION: - decodeStringSection(); - break; - case TABLE_SECTION: - decodeTableSection(); - break; - case FUNCTION_SECTION: - decodeFunctionSection(); - break; - case START_SECTION: - decodeStartSection(); - break; - case GLOBAL_SECTION: - decodeGlobalSection(); - break; - case GLOBAL_VARIABLE_SECTION: - decodeGlobalVariableSection(); - break; - case STYLE_SECTION: - decodeStyleSection(); - break; - case ARRAY_SECTION: - decodeArraySection(); - break; - case REF_SECTION: - decodeRefSection(); - break; - case CLASS_SECTION: - decodeClassSection(); - break; - default: - break; - } - } - return true; -} - -void ExecState::decodeStringSection() -{ - BinaryFile* file = BinaryFile::instance(); - - unsigned count = 0; - file->read((char*)&count, sizeof(u_int32_t)); - if (count == 0) { - return; - } - - for (int i=0; iread(&c, sizeof(char)); - if (c == 0) { - break; - } - str += c; - } - string_table_->StringFromUTF8(str); - } -} - -void ExecState::decodeTableSection() { - BinaryFile* file = BinaryFile::instance(); - - unsigned count = 0; - file->read((char*)&count, sizeof(u_int32_t)); - if (count == 0) { - return; - } - - for (int i=0; iCreateTable(); - Table* table = reinterpret_cast
(tableValue.gc); - unsigned mapSize=0; - file->read((char*)&mapSize, sizeof(u_int32_t)); - for (int j=0; jread(&c, sizeof(char)); - if (c == 0) { - break; - } - str += c; - } - Value value; - decodeValue(value); - table->map.insert(std::make_pair(str, value)); - } - } -} - -void ExecState::decodeFunctionSection() { - BinaryFile* file = BinaryFile::instance(); - - unsigned count = 0; - file->read((char*)&count, sizeof(u_int32_t)); - if (count == 0) { - return; - } - - std::vector func_states; - for (int i=0; iread((char*)&super_index, sizeof(int32_t)); - func_state->set_super_index(super_index); - - bool is_class_func = false; - file->read((char*)&is_class_func, sizeof(int8_t)); - func_state->set_is_class_func(is_class_func); - - int argc = 0; - file->read((char*)&argc, sizeof(int32_t)); - func_state->argc() = argc; - - unsigned op_code_count = 0; - file->read((char*)&op_code_count, sizeof(u_int32_t)); - for (int j=0; jread((char*)&opcode, sizeof(u_int32_t)); - func_state->AddInstruction(opcode); - } - unsigned local_count = 0; - file->read((char*)&local_count, sizeof(u_int32_t)); - for (int j=0; jAddConstant(value); - } - func_states.push_back(func_state); - } - - func_state_.reset(func_states[0]); - for (auto func : func_states) { - int index = func->super_index(); - if (index > -1) { - func_states[index]->AddChild(func); - } - } -} - -void ExecState::decodeStartSection() { - BinaryFile* file = BinaryFile::instance(); - unsigned start_index; - file->read((char*)&start_index, sizeof(u_int32_t)); -} - -void ExecState::decodeGlobalSection() { - BinaryFile* file = BinaryFile::instance(); - - unsigned count = 0; - file->read((char*)&count, sizeof(u_int32_t)); - - int init_data_index = -1; - int weex_data_index = -1; - file->read((char*)&init_data_index, sizeof(int32_t)); - file->read((char*)&weex_data_index, sizeof(int32_t)); - - unsigned register_size = global_->register_size(); - for (int i=0; iAdd("_init_data", value); - } else if (register_size + i == weex_data_index) { - global_->Add("__weex_data__", value); - } else { - global_->Add(value); - } - } - } -} - -void ExecState::decodeGlobalVariableSection() { - BinaryFile* file = BinaryFile::instance(); - - unsigned count = 0; - file->read((char*)&count, sizeof(u_int32_t)); - if (count == 0) { - return; - } - - for (int i=0; iread(&c, sizeof(char)); - if (c == 0) { - break; - } - key += c; - } - - long value; - file->read((char*)&value, sizeof(int64_t)); - global_variables_.insert(std::pair(key, value)); - } -} - -void ExecState::decodeStyleSection() { - BinaryFile* file = BinaryFile::instance(); - - unsigned count = 0; - file->read((char*)&count, sizeof(u_int32_t)); - if (count == 0) { - return; - } - - for (int i=0; iread((char*)&itemsSize, sizeof(u_int32_t)); - //json11::Json::object items; - std::unordered_map items; - for (int j=0; jread(&c, sizeof(char)); - if (c == 0) { - break; - } - key += c; - } - - std::string value; - char v; - while (true) { - file->read(&v, sizeof(char)); - if (v == 0) { - break; - } - value += v; - } - json11::Json json(value); - items.insert(std::make_pair(std::move(key), std::move(json))); - } - json11::Json json(std::move(items)); - styles_.insert(std::make_pair(value.index, std::move(json))); - } -} - -void ExecState::decodeArraySection() { - BinaryFile* file = BinaryFile::instance(); - unsigned count = 0; - file->read((char*)&count, sizeof(u_int32_t)); - for (int i=0; iCreateArray(); - Array* array = reinterpret_cast(value.gc); - unsigned itemSize = 0; - file->read((char*)&itemSize, sizeof(u_int32_t)); - for (int j=0; jitems.push_back(itemValue); - } - } -} - -void ExecState::decodeRefSection() { - BinaryFile* file = BinaryFile::instance(); - unsigned count = 0; - file->read((char*)&count, sizeof(u_int32_t)); - for (int i=0; iread((char*)®ister_id, sizeof(int64_t)); - ValueRef *ref = new ValueRef(nullptr, register_id); - ref->func_index_ = value.index; - decodeValue(ref->value_); - refs_.push_back(ref); - } -} - -void ExecState::decodeClassSection() { - BinaryFile* file = BinaryFile::instance(); - unsigned count = 0; - file->read((char*)&count, sizeof(u_int32_t)); - - size_t size = class_factory_->descs().size(); - for (int i=0; iCreateClassDescriptor(nullptr); - ClassDescriptor* desc = reinterpret_cast(value.gc); - int super_index = -1; - file->read((char*)&super_index, sizeof(int32_t)); - desc->super_index_ = super_index; - - unsigned static_func_size = 0; - file->read((char*)&static_func_size, sizeof(u_int32_t)); - for (int j=0; jread((char*)&length, sizeof(u_int32_t)); - if (length > 0) { - std::unique_ptr str(new char[length]); - file->read(str.get(), sizeof(char)*length); - desc->static_funcs_->Add(str.get(), static_value); - } else { - desc->static_funcs_->Add(static_value); - } - } - - unsigned class_func_size = 0; - file->read((char*)&class_func_size, sizeof(u_int32_t)); - for (int j=0; jread((char*)&length, sizeof(u_int32_t)); - if (length > 0) { - std::unique_ptr str(new char[length]); - file->read(str.get(), sizeof(char)*length); - desc->funcs_->Add(str.get(), class_value); - } else { - desc->funcs_->Add(class_value); - } - } - } -} - -void ExecState::decodeValue(Value &value) { - BinaryFile* file = BinaryFile::instance(); - unsigned valueType; - file->read((char*)&valueType, sizeof(u_int32_t)); - value.type = Value::Type(valueType); - - switch (valueType) { - case Value::Type::TABLE: - case Value::Type::STRING: - case Value::Type::FUNC: - case Value::Type::ARRAY: - case Value::Type::CLASS_DESC: { - value.gc = nullptr; - file->read((char*)&(value.index), sizeof(int32_t)); - } - break; - case Value::Type::INT: { - file->read((char*)&(value.i), sizeof(int64_t)); - } - break; - case Value::Type::NUMBER: { - file->read((char*)&(value.n), sizeof(double)); - } - break; - case Value::Type::BOOL: { - file->read((char*)&(value.b), sizeof(char)); - } - break; - default: - break; - } -} - -void ExecState::endDecode() { - BinaryFile* file = BinaryFile::instance(); - file->readFinish(); - - std::vector
tables = class_factory_->tables(); - for (auto table : tables ) { - for (auto &map : table->map) { - Value& value = map.second; - serializeValue(value); - } - } - - std::vector& constants = func_state_->constants(); - for (auto &value : constants) { - serializeValue(value); - } - std::vector children = func_state_->getAllChildren(); - for (auto func_state : children) { - std::vector& child_constants = func_state->constants(); - for (auto &value : child_constants) { - serializeValue(value); - } - } - - for (int i=0; isize(); i++) { - Value* value = global_->Find(i); - serializeValue(*value); - } - - std::map& styles = render_context_->style_json(); - for (auto &style : styles_) { - Value value; - value.index = style.first; - value.type = Value::Type::STRING; - serializeValue(value); - styles.insert(std::make_pair(value.str->c_str(), style.second)); - } - - std::vector arrays = class_factory_->arrays(); - for (auto array : arrays) { - for (auto &value : array->items) { - serializeValue(value); - } - } - - for (auto ref : refs_) { - if (ref->func_index_ == 0) { - ref->func_state_ = func_state_.get(); - } else { - ref->func_state_ = func_state_->getAllChildren()[ref->func_index_-1]; - } - serializeValue(ref->value_); - } - - std::vector descs = class_factory_->descs(); - int count = 0; - for (auto desc : descs) { - count++; - if (count <= 4) { - continue; - } - if (desc->super_index_ != -1) { - desc->p_super_ = descs[desc->super_index_]; - } - for (int i=0; istatic_funcs_->size(); i++) { - Value* value = desc->static_funcs_->Find(i); - serializeValue(*value); - } - for (int i=0; ifuncs_->size(); i++) { - Value* value = desc->funcs_->Find(i); - serializeValue(*value); - } - } -} - -void ExecState::serializeValue(Value &value) { - if (value.index == -1) { - return; - } - - if (value.type == Value::Type::TABLE) { - std::vector
tables = class_factory_->tables(); - value.gc = reinterpret_cast(tables[value.index]); - } - - if (value.type == Value::Type::STRING) { - const std::vector>>& store = string_table_->store(); - if (value.index >= store.size()) { - value.str = store[0].second.get(); - } else { - value.str = store[value.index].second.get(); - } - } - - if (value.type == Value::Type::FUNC) { - if (value.index == 0) { - value.f = func_state_.get(); - } else { - value.f = func_state_->getAllChildren()[value.index-1]; - } - } - - if (value.type == Value::Type::ARRAY) { - std::vector arrays = class_factory_->arrays(); - value.gc = reinterpret_cast(arrays[value.index]); - } - - if (value.type == Value::Type::CLASS_DESC) { - std::vector descs = class_factory_->descs(); - value.gc = reinterpret_cast(descs[value.index]); - } -} - const Value ExecState::Call(const std::string& func_name, const std::vector& args) { Value ret; do { @@ -999,6 +178,23 @@ const Value ExecState::Call(const std::string& func_name, const std::vector& args) { + Value ret; + do { + Value functor; + SetGCFuncValue(&functor, reinterpret_cast(func)); + **stack_->top() = functor; + int index = 0; + for (int i = 0; i < args.size(); i++) { + *(*stack_->top() + i + 1 + index) = args[i]; + } + CallFunction(*stack_->top(), args.size(), &ret); + + } while (0); + + return ret; +} + const Value ExecState::Call(FuncState *func_state, const std::vector& args) { Value ret; do { @@ -1065,7 +261,6 @@ void ExecState::Register(const std::string& name, CFunction func) { void ExecState::Register(const std::string& name, Value value) { global()->Add(name, value); - global()->incrementRegisterSize(); } void ExecState::CallFunction(Value *func, size_t argc, Value *ret) { @@ -1075,23 +270,24 @@ void ExecState::CallFunction(Value *func, size_t argc, Value *ret) { frame.reg = func; frames_.push_back(frame); auto result = reinterpret_cast(func->cf)(this); - if (ret != nullptr && !IsNil(&result)) { + if (ret) { *ret = result; } stack_->reset(); frames_.pop_back(); } else { - if (argc < func->f->argc()) { - size_t size = (func->f->argc() - argc) * sizeof(Value); + FuncState *func_state = func->type == Value::Type::FUNC ? func->f : ValueTo(func)->func_; + if (argc < func_state->argc()) { + size_t size = (func_state->argc() - argc) * sizeof(Value); memset(func + argc + 1, 0, size); } *stack_->top() = func + argc; Frame frame; - frame.func = func; + frame.func = func_state; frame.reg = func; - frame.pc = &(*func->f->instructions().begin()); - frame.end = &(*func->f->instructions().end()); + frame.pc = &(*func_state->instructions().begin()); + frame.end = &(*func_state->instructions().end()); frames_.push_back(frame); resetArguments(func, argc); vm_->RunFrame(this, frame, ret); diff --git a/weex_core/Source/core/data_render/exec_state.h b/weex_core/Source/core/data_render/exec_state.h index c189bbd853..398e73b7c3 100644 --- a/weex_core/Source/core/data_render/exec_state.h +++ b/weex_core/Source/core/data_render/exec_state.h @@ -17,8 +17,8 @@ * under the License. */ -#ifndef CORE_DATA_RENDER_CONTEXT_H_ -#define CORE_DATA_RENDER_CONTEXT_H_ +#ifndef CORE_DATA_RENDER_EXEC_STATE_H +#define CORE_DATA_RENDER_EXEC_STATE_H #include #include @@ -43,9 +43,13 @@ class ValueRef { public: ValueRef(FuncState *func_state, long register_id) : func_state_(func_state), register_id_(register_id), ref_id_(gs_ref_id++), func_index_(-1) { SetNil(&value_); }; inline int ref_id() { return ref_id_; } + inline void SetClosure(FuncClosure *closure) { closure_ = closure; } inline FuncState *func_state() { return func_state_; } inline long register_id() { return register_id_; } inline Value &value() { return value_; } + inline bool &is_closure() { return is_closure_; } + inline FuncClosure *closure() { return closure_; } + static void reset() { gs_ref_id = 0; } ~ValueRef() {} private: static int gs_ref_id; @@ -54,13 +58,30 @@ class ValueRef { long register_id_; int func_index_; Value value_; + FuncClosure *closure_{nullptr}; + bool is_closure_{false}; }; struct ClassInstance; +class FuncClosure { +public: + explicit FuncClosure(ValueRef *ref); + virtual ~FuncClosure() {} + inline void SetValueRef(ValueRef *ref) { ref_ = ref; value_.ref = ref ? &ref->value() : nullptr; } + inline FuncState *func_state() { return func_state_; } + inline long register_id() { return register_id_; } + inline Value &value() { return value_; } +private: + FuncState *func_state_{nullptr}; + long register_id_{-1}; + Value value_; + ValueRef *ref_; +}; + class FuncState { public: - FuncState() : instructions_(), constants_(), children_(), super_index_(-1) {} + FuncState() : instructions_(), args_(), in_closure_(), out_closure_(), constants_(), children_(), super_index_(-1), in_closure_refs_(), out_closure_refs_() {} virtual ~FuncState() {} int AddConstant(Value value) { @@ -72,9 +93,20 @@ class FuncState { constants_.push_back(std::move(value)); return (int)constants_.size() - 1; } + void AddInClosure(ValueRef *ref) { + if (std::find(in_closure_.begin(), in_closure_.end(), ref) == in_closure_.end()) { + in_closure_.push_back(ref); + } + } + void AddOutClosure(ValueRef *ref) { + if (std::find(out_closure_.begin(), out_closure_.end(), ref) == out_closure_.end()) { + out_closure_.push_back(ref); + } + } inline Value *GetConstant(int index) { return &constants_[index]; } inline size_t GetConstantSize() { return constants_.size();} + inline bool Inclusive(long arg) { return std::find(args_.begin(), args_.end(), arg) == args_.end() ? false : true; } inline size_t AddInstruction(Instruction i) { instructions_.push_back(i); return instructions_.size() - 1; @@ -84,45 +116,53 @@ class FuncState { return pos; } inline std::vector& instructions() { return instructions_; } - inline void AddChild(FuncState* func) { + inline void AddChild(FuncState *func) { func->super_func_ = this; children_.push_back(std::unique_ptr(func)); } inline const std::vector>& children() { return children_; } - inline FuncState* GetChild(size_t pos) { return children_[pos].get(); } - inline std::vector& constants() {return constants_;} - inline FuncState* super_func() {return super_func_;} - inline void set_super_func(FuncState* func) {super_func_ = func;} + inline FuncState *GetChild(size_t pos) { return children_[pos].get(); } + inline std::vector& constants() { return constants_; } + inline FuncState *super_func() { return super_func_; } + inline void set_super_func(FuncState *func) { super_func_ = func; } inline void set_is_class_func(bool is_class_func) { is_class_func_ = is_class_func; } inline bool is_class_func() { return is_class_func_; } inline ClassInstance * &class_inst() { return class_inst_; } inline int &argc() { return argc_; } - std::vector getAllChildren() { - std::vector all_children; + inline std::vector &args() { return args_; } + std::vector all_childrens() { + std::vector all_childrens; for (auto &child : children_) { - all_children.push_back(child.get()); - std::vector children = child->getAllChildren(); - all_children.insert(all_children.end(), children.begin(), children.end()); + all_childrens.push_back(child.get()); + std::vector children = child->all_childrens(); + all_childrens.insert(all_childrens.end(), children.begin(), children.end()); } - return all_children; + return all_childrens; } - - inline int super_index() const {return super_index_;} - inline void set_super_index(int super_index) {super_index_ = super_index;} - + inline std::vector &in_closure() { return in_closure_; } + inline std::vector &out_closure() { return out_closure_; } + inline int super_index() const { return super_index_; } + inline void set_super_index(int super_index) { super_index_ = super_index; } + inline std::vector& in_closure_refs() { return in_closure_refs_; } + inline std::vector& out_closure_refs() { return out_closure_refs_; } private: std::vector instructions_; std::vector constants_; std::vector> children_; + std::vector args_; + std::vector in_closure_; + std::vector out_closure_; + std::vector in_closure_refs_; + std::vector out_closure_refs_; FuncState *super_func_{nullptr}; int super_index_; bool is_class_func_{false}; ClassInstance *class_inst_{nullptr}; int argc_{0}; }; - + // TODO Each Func should contain a stack whose size is 256 class ExecStack { public: @@ -134,73 +174,43 @@ class ExecStack { std::vector stack_; Value *top_; }; - + class ExecState { public: - ExecState(VM* vm); - virtual ~ExecState() {} + ExecState(VM *vm); + virtual ~ExecState(); void Compile(std::string& error); void Execute(std::string& error); const Value Call(const std::string& func_name, const std::vector& args); const Value Call(Value *func, const std::vector& args); const Value Call(FuncState *func, const std::vector& args); - + const Value Call(FuncInstance *func, const std::vector& args); size_t GetArgumentCount(); - Value* GetArgument(int index); + Value *GetArgument(int index); ValueRef *AddRef(FuncState *func_state, long register_id); ValueRef *FindRef(int index); void Register(const std::string& name, CFunction function); void Register(const std::string& name, Value value); - std::vector &refs() { return refs_; }; - inline Variables* global() { return global_.get(); } - inline ExecStack* stack() { return stack_.get(); } - inline StringTable* string_table() { return string_table_.get(); } - inline VNodeRenderContext* context() { return render_context_.get(); } + inline std::vector &refs() { return refs_; }; + inline Variables *global() { return global_.get(); } + inline void reset(FuncState *func_state) { func_state_.reset(func_state); } + inline FuncState *func_state() { return func_state_.get(); } + inline ExecStack *stack() { return stack_.get(); } + inline StringTable *string_table() { return string_table_.get(); } + inline VNodeRenderContext *context() { return render_context_.get(); } inline ClassFactory *class_factory() { return class_factory_.get(); } - - void startEncode(); - void endEncode(); - - bool startDecode(); - void endDecode(); - + inline uint32_t global_compile_index() { return global_compile_index_; } + inline uint32_t class_compile_index() { return class_compile_index_; } + inline uint32_t string_compile_index() { return string_compile_index_; } + inline std::unordered_map& global_variables() { return global_variables_; } private: friend class VM; friend class CodeGenerator; - - void encodeGlobalSection(); - void encodeGlobalVariableSection(); - void encodeFunctionSection(); - void encodeStartSection(); - void encodeTableSection(); - void encodeStringSection(); - void encodeStyleSection(); - void encodeArraySection(); - void encodeRefSection(); - void encodeClassSection(); - void encodeValue(const Value &value); - - void decodeValue(Value &value); - void decodeStringSection(); - void decodeTableSection(); - void decodeFunctionSection(); - void decodeStartSection(); - void decodeGlobalSection(); - void decodeGlobalVariableSection(); - void decodeStyleSection(); - void decodeArraySection(); - void decodeRefSection(); - void decodeClassSection(); - void serializeValue(Value &value); void resetArguments(Value *func, size_t argc); void CallFunction(Value *func, size_t argc, Value *ret); int findSuperIndex(const std::vector& func_states); - - VM* vm_; - + VM *vm_; std::unique_ptr class_factory_; - - std::vector frames_; std::vector refs_; std::unique_ptr global_; @@ -210,10 +220,13 @@ class ExecState { std::unique_ptr render_context_; std::unordered_map global_variables_; std::unordered_map styles_; + uint32_t global_compile_index_{0}; + uint32_t class_compile_index_{0}; + uint32_t string_compile_index_{0}; }; } // namespace data_render } // namespace core } // namespace weex -#endif // CORE_DATA_RENDER_CONTEXT_H_ +#endif // CORE_DATA_RENDER_EXEC_STATE_H diff --git a/weex_core/Source/core/data_render/exec_state_binary.cc b/weex_core/Source/core/data_render/exec_state_binary.cc new file mode 100644 index 0000000000..0b19a00818 --- /dev/null +++ b/weex_core/Source/core/data_render/exec_state_binary.cc @@ -0,0 +1,624 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include "core/data_render/exec_state_binary.h" +#include "core/data_render/common_error.h" +#include "core/data_render/vm.h" +#include "core/data_render/exec_state.h" +#include "third_party/json11/json11.hpp" +#include "core/data_render/vnode/vnode_exec_env.h" +#include "base/LogDefines.h" + +namespace weex { +namespace core { +namespace data_render { + +#define EXECSTATE_ENCODING_COMPARE 0 + +std::once_flag device_little_endian; + +static bool gs_device_is_little_endian = false; +static uint8_t gs_op_code_bits = 0; + +void determine_little_endian() +{ + short i = 0x1; + gs_device_is_little_endian = !((i >> 8) == 0x1); + gs_op_code_bits = 1; + uint32_t op_code_value = OP_INVALID; + while (op_code_value / 2 > 0) { + op_code_value = op_code_value / 2; + gs_op_code_bits++; + } +} + +bool ExecStateEncoder::encoding(std::string &err) { + bool finished = false; + do { + try { + SectionHeader header(this); + if (!header.encoding()) { + err = "header encoding error"; + break; + } + SectionString string(this); + if (!string.encoding()) { + err = "string section encoding error"; + break; + } + SectionData data(this); + if (!data.encoding()) { + err = "data section encoding error"; + break; + } + SectionFunction function(this, gs_op_code_bits); + if (!function.encoding()) { + err = "function section encoding error"; + break; + } + SectionClass classDescriptor(this); + if (!classDescriptor.encoding()) { + err = "class encoding error"; + break; + } + SectionGlobalConstants constants(this); + if (!constants.encoding()) { + err = "global constants section encoding error"; + break; + } + SectionGlobalVariables variables(this); + if (!variables.encoding()) { + err = "global variables section encoding error"; + break; + } + SectionStyles styles(this); + if (!styles.encoding()) { + err = "style section encoding error"; + break; + } + SectionVaueRef valueRef(this); + if (!valueRef.encoding()) { + err = "value ref section encoding error"; + break; + } + } + catch (std::exception &e) { + auto error = static_cast(&e); + if (error) { + err = error->what(); + std::cerr << error->what() << std::endl; + } + break; + } + finished = true; + + } while (0); + + return finished; +} + +bool ExecStateDecoder::decoding(std::string &err) { + bool finished = false; + do { + if (stream_->Seek(0, SEEK_END) <= 0) { + err = "file length zero error"; + break; + } + int64_t fileSize = stream_->Tell(); + if (stream_->Seek(0, SEEK_SET) < 0) { + err = "file length zero error"; + break; + } + try { + do { + uint16_t section = 0; + uint32_t section_length = 0; + if ((section_length = stream_->ReadTarget(§ion, NULL, NULL)) == 0) { + err = "read section flag error"; + break; + } + switch (section) { + case ExecSection::EXEC_SECTION_HEADER: + { + SectionHeader header(this, section_length); + if (!header.decoding()) { + throw EncoderError("header section decoding error"); + } + break; + } + case ExecSection::EXEC_SECTION_STRING: + { + SectionString string(this, section_length); + if (!string.decoding()) { + throw EncoderError("string section decoding error"); + } + break; + } + case ExecSection::EXEC_SECTION_DATA: + { + SectionData data(this, section_length); + if (!data.decoding()) { + throw EncoderError("data section decoding error"); + } + break; + } + case ExecSection::EXEC_SECTION_FUNCTION: + { + SectionFunction function(this, gs_op_code_bits, section_length); + if (!function.decoding()) { + throw EncoderError("function section decoding error"); + } + break; + } + case ExecSection::EXEC_SECTION_GLOBAL_CONSTANTS: + { + SectionGlobalConstants constants(this, section_length); + if (!constants.decoding()) { + throw EncoderError("function global constants decoding error"); + } + break; + } + case ExecSection::EXEC_SECTION_GLOBAL_VARIABLES: + { + SectionGlobalVariables variables(this, section_length); + if (!variables.decoding()) { + throw EncoderError("function global variables decoding error"); + } + break; + } + case ExecSection::EXEC_SECTION_STYLES: + { + SectionStyles styles(this, section_length); + if (!styles.decoding()) { + throw EncoderError("function global variables decoding error"); + } + break; + } + case ExecSection::EXEC_SECTION_VALUEREF: + { + SectionVaueRef valueRef(this, section_length); + if (!valueRef.decoding()) { + throw EncoderError("value ref decoding error"); + } + break; + } + case ExecSection::EXEC_SECTION_CLASS: + { + SectionClass classDescriptor(this, section_length); + if (!classDescriptor.decoding()) { + throw EncoderError("class decoding error"); + } + break; + } + default: + { + if (stream_->Seek(section_length, SEEK_CUR) < 0) { + throw EncoderError("section decoding length error"); + } + break; + } + } + + } while (stream_->Tell() < fileSize); + } + catch (std::exception &e) { + auto error = static_cast(&e); + if (error) { + err = error->what(); + std::cerr << error->what() << std::endl; + } + break; + } + finished = true; + + } while (0); + + return finished; +} + +uint32_t fStream::Read(void *buffer, uint32_t size, uint32_t cnt) { + return Read(buffer, size * cnt) / size; +} + +uint32_t fStream::ReadTarget(uint16_t *target, uint8_t *buffer, uint32_t *size) { + uint32_t bytesRead = 0; + do { + uint32_t flags = 0; + uint32_t target_length = 0; + uint16_t target_value = 0; + uint32_t size_length = 0; + uint32_t value_length = 0; + if (Read(&flags, 1, 1) != 1) { + break; + } + if (SECTION_TEST_FLAG(flags, SECTION_EXT_MASK)) { + if (Read((uint8_t *)&flags + 1, 1, 3) != 3) { + break; + } + } + // tag + target_length = SECTION_TEST_FLAG(flags, SECTION_TAG_MASK) ? 2 : 1; + if (Read(&target_value, 1, target_length) != target_length) { + break; + } + // length + SECTION_GET_LENGTH_LEN(flags, size_length); + if (size_length == 0) { + value_length = (flags & SECTION_VALUE_MASK) + 1; // 0:1 1:2 2:4 3:8 + if (value_length == 3) { + value_length = 4; + } + else if (value_length == 4) { + value_length = 8; + } + } + else { + if (Read(&value_length, 1, size_length) != size_length) { + break; + } + } + if (target) { + *target = target_value; + } + if (buffer == NULL || size == NULL || *size == 0 || value_length == 0) { + bytesRead = value_length; + break; + } + uint32_t buffer_length = *size; + *size = value_length; + if (buffer_length > value_length) { + buffer_length = value_length; + } + if (Read(buffer, 1, buffer_length) != buffer_length) { + break; + } + if (buffer_length < value_length) { + Seek(value_length - buffer_length, SEEK_CUR); + } + bytesRead = value_length; + + } while (0); + + return bytesRead; +} + +uint32_t fStream::Read(void *buffer, uint32_t size) { + uint32_t readBytes = 0; + do { + int64_t left = size_ - seek_; + if (left < 0) { + break; + } + if (left < (int64_t)size) { + size = (uint32_t)left; + } + memcpy(buffer, buffer_ + seek_, size); + seek_ += size; + readBytes = size; + + } while (0); + + return readBytes; +} + +int64_t fStream::Seek(int64_t pos, int type) { + switch (type) { + case SEEK_SET: + { + seek_ = pos > size_ ? size_ : pos; + break; + } + case SEEK_CUR: + { + if (seek_ + pos > size_) { + seek_ = size_; + } + else { + seek_ += pos; + } + break; + } + case SEEK_END: + { + if (pos >= 0) { + seek_ = size_; + } + else { + if (seek_ <= (uint64_t)(-pos)) { + seek_ = 0; + } + else { + seek_ -= (uint64_t)(-pos); + } + } + break; + } + + } + return (int64_t)seek_; +} + +#if EXECSTATE_ENCODING_COMPARE +static ExecState *gs_encoder = nullptr; +#endif + +bool WXExecEncoder(std::string &input, std::string &path, std::string &error) { + bool finished = false; + VM *vm = nullptr; + ExecState *exec_state = nullptr; + FILE *fout = nullptr; + do { + std::call_once(device_little_endian, determine_little_endian); + if (!gs_device_is_little_endian) { + error = "device must be little endian error"; + break; + } + fout = fopen(path.c_str(), "wb"); + if (fout == nullptr) { + error = "can't open " + path; + break; + } + if (!input.length()) { + error = "source is nil"; + break; + } + vm = new VM(); + if (!vm) { + error = "low memory"; + break; + } + exec_state = new ExecState(vm); + VNodeExecEnv::ImportExecEnv(exec_state); + if (!exec_state) { + error = "low memory"; + break; + } + std::string err; + json11::Json json = json11::Json::parse(input, err); + if (!err.empty() || json.is_null()) { + exec_state->context()->raw_source() = input; + } + else { + exec_state->context()->raw_json() = json; + } + if (exec_state->global()->IndexOf("__weex_data__") < 0) { + exec_state->global()->Set("__weex_data__", Value()); + } + if (exec_state->global()->IndexOf("_init_data") < 0) { + exec_state->global()->Set("_init_data", Value()); + } + exec_state->Compile(err); + if (!err.empty()) { + error = err; + break; + } + ExecStateEncoder encoder(exec_state, fout); + if (!encoder.encoding(err)) { + error = err; + break; + } +#if EXECSTATE_ENCODING_COMPARE + gs_encoder = exec_state; +#endif + finished = true; + + } while (0); + +#if ! EXECSTATE_ENCODING_COMPARE + if (exec_state) { + delete exec_state; + } +#endif + if (vm) { + delete vm; + } + LOGD("encoding file size:%.02fK\n", (double)ftell(fout) / 1024); + if (fout) { + fclose(fout); + } + return finished; +} + +#if EXECSTATE_ENCODING_COMPARE +static void compare(ExecState *encoder, ExecState *decoder); +#endif + +bool WXExecDecoder(ExecState *exec_state, uint8_t *buffer, size_t size, std::string &error) { + bool finished = false; + do { + std::call_once(device_little_endian, determine_little_endian); + if (!gs_device_is_little_endian) { + error = "device must be little endian error"; + break; + } + std::string err; + ExecStateDecoder decoder(exec_state, buffer, size); + if (!decoder.decoding(err)) { + error = err; + break; + } +#if EXECSTATE_ENCODING_COMPARE + compare(gs_encoder, exec_state); +#endif + finished = true; + + } while (0); + + return finished; +} + +#if EXECSTATE_ENCODING_COMPARE +static void compare_value(Value *encoder_value, Value *decoder_value); +static void compare_variables(Variables *encoder_var, Variables *decoder_var, bool map_diff = true); +static void compare_value_ref(ValueRef *encoder_ref, ValueRef *decoder_ref); +static void compare_func_state(FuncState *encoder_func_state, FuncState *decoder_func_state, bool is_ref = true, bool is_children = true); +static void compare_class_desc(ClassDescriptor *encoder_desc, ClassDescriptor *decoder_desc) { + if (encoder_desc->p_super_) { + assert(decoder_desc->p_super_); + compare_class_desc(encoder_desc->p_super_, decoder_desc->p_super_); + } + compare_variables(encoder_desc->static_funcs_.get(), decoder_desc->static_funcs_.get()); + compare_variables(encoder_desc->funcs_.get(), decoder_desc->funcs_.get()); +} + +static void compare_func_state(FuncState *encoder_func_state, FuncState *decoder_func_state, bool is_ref, bool is_children) { + assert(encoder_func_state->is_class_func() == decoder_func_state->is_class_func()); + assert(encoder_func_state->argc() == decoder_func_state->argc()); + for (int i = 0; i < encoder_func_state->args().size(); i++) { + assert(encoder_func_state->args()[i] == decoder_func_state->args()[i]); + } + assert(encoder_func_state->in_closure().size() == decoder_func_state->in_closure().size()); + if (is_ref) { + for (int i = 0; i < encoder_func_state->in_closure().size(); i++) { + compare_value_ref(encoder_func_state->in_closure()[i], decoder_func_state->in_closure()[i]); + } + } + assert(encoder_func_state->out_closure().size() == decoder_func_state->out_closure().size()); + if (is_ref) { + for (int i = 0; i < encoder_func_state->out_closure().size(); i++) { + ValueRef *ref_encoder = encoder_func_state->out_closure()[i]; + ValueRef *ref_decoder = decoder_func_state->out_closure()[i]; + compare_value_ref(ref_encoder, ref_decoder); + } + } + assert(encoder_func_state->instructions().size() == decoder_func_state->instructions().size()); + for (int i = 0; i < encoder_func_state->instructions().size(); i++) { + assert(encoder_func_state->instructions()[i] == decoder_func_state->instructions()[i]); + } + assert(encoder_func_state->constants().size() == decoder_func_state->constants().size()); + for (int i = 0; i < encoder_func_state->constants().size(); i++) { + Value encoder_value = encoder_func_state->constants()[i]; + Value decoder_value = decoder_func_state->constants()[i]; + compare_value(&encoder_value, &decoder_value); + } + if (is_children) { + auto encoder_all_childrens = encoder_func_state->all_childrens(); + auto decoder_all_childrens = decoder_func_state->all_childrens(); + assert(encoder_all_childrens.size() == decoder_all_childrens.size()); + for (int i = 0; i < encoder_all_childrens.size(); i++) { + compare_func_state(encoder_all_childrens[i], decoder_all_childrens[i], true, false); + } + } +} + +static void compare_value(Value *encoder_value, Value *decoder_value) { + assert(encoder_value->type == decoder_value->type); + switch (encoder_value->type) { + case Value::STRING: + { + assert(std::string(encoder_value->str->c_str()) == std::string(decoder_value->str->c_str())); + break; + } + case Value::FUNC: + { + compare_func_state(encoder_value->f, decoder_value->f); + break; + } + case Value::CLASS_DESC: + { + compare_class_desc(ValueTo(encoder_value), ValueTo(decoder_value)); + break; + } + default: + assert(*encoder_value == *decoder_value); + break; + } +} + +static void compare_variables(Variables *encoder_var, Variables *decoder_var, bool map_diff) { + assert(encoder_var->size() == encoder_var->size()); + for (int i = 0; i < encoder_var->size(); i++) { + Value *encoder_value = encoder_var->Find(i); + Value *decoder_value = encoder_var->Find(i); + compare_value(encoder_value, decoder_value); + } + if (map_diff) { + std::map &encoder_var_map = (std::map &)encoder_var->map(); + std::map &decoder_var_map = (std::map &)decoder_var->map(); + assert(encoder_var_map.size() == decoder_var_map.size()); + std::map::iterator encoder_iter = encoder_var_map.begin(); + std::map::iterator decoder_iter = decoder_var_map.begin(); + for (int i = 0; i < encoder_var_map.size(); i++) { + LOGD("compare_variables key:%s : %s\n", encoder_iter->first.c_str(), decoder_iter->first.c_str()); + assert(encoder_iter->first == decoder_iter->first); + assert(encoder_iter->second == decoder_iter->second); + encoder_iter++; + decoder_iter++; + } + } +} + +static void compare_value_ref(ValueRef *encoder_ref, ValueRef *decoder_ref) { + int encoder_ref_id = encoder_ref->ref_id(); + int decoder_ref_id = decoder_ref->ref_id(); + assert(encoder_ref_id == decoder_ref_id); + assert(encoder_ref->register_id() == decoder_ref->register_id()); + compare_func_state(encoder_ref->func_state(), decoder_ref->func_state(), false, false); +} + +static void compare(ExecState *encoder, ExecState *decoder) { + do { + StringTable *encoder_string_table = encoder->string_table(); + StringTable *decoder_string_table = encoder->string_table(); + assert(encoder_string_table->store().size() == decoder_string_table->store().size()); + for (int i = 0; i < encoder_string_table->store().size(); i++) { + assert(encoder_string_table->store()[i].first == decoder_string_table->store()[i].first); + std::string encoder_string = encoder_string_table->store()[i].second->c_str(); + std::string decoder_string = decoder_string_table->store()[i].second->c_str(); + assert(encoder_string == decoder_string); + } + FuncState *encoder_func_state = encoder->func_state(); + FuncState *decoder_func_state = decoder->func_state(); + compare_func_state(encoder_func_state, decoder_func_state); + std::vector encoder_descs = encoder->class_factory()->descs(); + std::vector decoder_descs = decoder->class_factory()->descs(); + assert(encoder_descs.size() == decoder_descs.size()); + for (int i = 0; i < encoder_descs.size(); i++) { + compare_class_desc(encoder_descs[i], decoder_descs[i]); + } + compare_variables(encoder->global(), decoder->global(), false); + std::unordered_map &encoder_global_variables = encoder->global_variables(); + std::unordered_map &decoder_global_variables = decoder->global_variables(); + assert(encoder_global_variables.size() == decoder_global_variables.size()); + std::unordered_map::iterator encoder_iter = encoder_global_variables.begin(); + std::unordered_map::iterator decoder_iter = encoder_global_variables.begin(); + for (int i = 0; i < encoder_global_variables.size(); i++) { + LOGD("compare map key:%s : %s\n", encoder_iter->first.c_str(), decoder_iter->first.c_str()); + assert(encoder_iter->first == decoder_iter->first); + assert(encoder_iter->second == decoder_iter->second); + encoder_iter++; + decoder_iter++; + } + std::vector &encoder_refs = encoder->refs(); + std::vector &decoder_refs = decoder->refs(); + assert(encoder_refs.size() == decoder_refs.size()); + for (int i = 0; i < encoder_refs.size(); i++) { + compare_value_ref(encoder_refs[i], decoder_refs[i]); + } + + } while (0); +} + +#endif + +} // namespace data_render +} // namespace core +} // namespace weex diff --git a/weex_core/Source/core/data_render/exec_state_binary.h b/weex_core/Source/core/data_render/exec_state_binary.h new file mode 100644 index 0000000000..8b77527b45 --- /dev/null +++ b/weex_core/Source/core/data_render/exec_state_binary.h @@ -0,0 +1,90 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CORE_DATA_RENDER_EXEC_STATE_BINARY_H +#define CORE_DATA_RENDER_EXEC_STATE_BINARY_H + +#include +#include +#include "core/data_render/exec_state_section.h" + +namespace weex { +namespace core { +namespace data_render { + +#define SECTION_VALUE_MASK 0x03 +#define SECTION_EXT_MASK 0x80 +#define SECTION_TAG_MASK 0x10 +#define SECTION_LEN_MASK 0x0c +#define SECTION_LEN_OFF 0x2 +#define SECTION_TEST_FLAG(flag, mask) (flag & mask) +#define SECTION_GET_LENGTH_LEN(flag, len) len = ((flags & SECTION_LEN_MASK) >> SECTION_LEN_OFF); if (len == 3) len = 4; + +class ExecState; +class fStream; + +class ExecStateEncoder { + friend class Section; +public: + ExecStateEncoder(ExecState *exec_state, FILE *fout) : exec_state_(exec_state), fout_(fout) {} + ~ExecStateEncoder() {} + bool encoding(std::string &err); + ExecState *exec_state() { return exec_state_; } +private: + FILE *fout_{nullptr}; + ExecState *exec_state_{nullptr}; +}; + +class fStream { + friend class Section; +public: + fStream(uint8_t *buffer, size_t size) : buffer_(buffer), size_(size), seek_(0) { } + using seek_type = int64_t; + using size_type = size_t; + int64_t Seek(int64_t pos, int type); + uint32_t Read(void *buffer, uint32_t size, uint32_t cnt); + uint32_t ReadTarget(uint16_t *target, uint8_t *buffer, uint32_t *size); + inline int64_t Tell() { return seek_; } +private: + uint32_t Read(void *buffer, uint32_t size); + seek_type seek_; + size_type size_; + uint8_t *buffer_; +}; + +class ExecStateDecoder { + friend class Section; +public: + ExecStateDecoder(ExecState *exec_state, uint8_t *buffer, size_t size) : stream_(new fStream(buffer, size)), exec_state_(exec_state) { } + ~ExecStateDecoder() { if (stream_) delete stream_; } + ExecState *exec_state() { return exec_state_; } + bool decoding(std::string &err); +private: + fStream *stream_; + ExecState *exec_state_{nullptr}; +}; + +bool WXExecEncoder(std::string &src, std::string &path, std::string &error); +bool WXExecDecoder(ExecState *exec_state, uint8_t *buffer, size_t size, std::string &error); + +} // namespace data_render +} // namespace core +} // namespace weex + +#endif // CORE_DATA_RENDER_EXEC_STATE_BINARY_H diff --git a/weex_core/Source/core/data_render/exec_state_section.cc b/weex_core/Source/core/data_render/exec_state_section.cc new file mode 100644 index 0000000000..b68ea2f068 --- /dev/null +++ b/weex_core/Source/core/data_render/exec_state_section.cc @@ -0,0 +1,3080 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "core/data_render/object.h" +#include "core/data_render/exec_state_section.h" +#include "core/data_render/exec_state_binary.h" +#include "core/data_render/common_error.h" +#include "core/data_render/exec_state.h" +#include "core/data_render/string_table.h" +#include "core/data_render/table.h" +#include "base/LogDefines.h" + +namespace weex { +namespace core { +namespace data_render { + +#define SECTION_FUNCTION_MAXARGS 256 +#define SECTION_VALUE_FINISHED 0xff +#define SECTION_SET_LENGTH_LEN_FLAG(flag, LenLen) if (LenLen == 4) LenLen = 3; flag |= (LenLen << SECTION_LEN_OFF); +#define SECTION_REGISTER_MAX 255 + +class CBitsReader { +public: + CBitsReader(std::uint8_t *data, std::uint32_t size) + : data_(data), + size_(size), + byteOffset_(0), + currentValue_(0), + currentBits_(0) {} + std::uint32_t remainingBytes() { + return size_ - byteOffset_; + } + std::uint32_t remainingBits() { + return 8 * (size_ - byteOffset_) + currentBits_; + } + std::uint32_t readStream(std::uint8_t *buffer, std::uint32_t size) { + std::uint32_t bytes_reading = 0; + do { + if (size > size_ - byteOffset_) { + break; + } + memcpy(buffer, data_ + byteOffset_, size); + byteOffset_ += size; + bytes_reading += size; + + } while (0); + + return bytes_reading; + } + std::uint32_t nextBits(std::uint32_t numBits) { + assert(numBits <= remainingBits() && "attempt to read more bits than available"); + // Collect bytes until we have enough bits: + while (currentBits_ < numBits) { + currentValue_ = (currentValue_ << 8) + (std::uint32_t)(data_[byteOffset_]); + currentBits_ = currentBits_ + 8; + byteOffset_ = byteOffset_ + 1; + } + // Extract result: + std::uint32_t remaining = currentBits_ - numBits; + std::uint32_t result = currentValue_ >> remaining; + // Update remaining bits: + currentValue_ = currentValue_ & ((1 << remaining) - 1); + currentBits_ = remaining; + return result; + } +private: + std::uint8_t *data_; + std::uint32_t byteOffset_; + std::uint32_t currentValue_; + std::uint32_t currentBits_; + std::uint32_t size_; +}; + +class CBitsWriter { +public: + CBitsWriter(std::uint8_t *data, std::uint32_t size) : data_(data), size_(size) {} + ~CBitsWriter() {} + virtual void WriteBits(std::uint32_t data, std::uint32_t numBits); + void WriteByte(std::uint8_t uByte); + virtual void Finish(); + std::uint8_t *GetBuffer(); + inline std::uint32_t Seek() { return seek_; }; + inline std::uint32_t Size() { return size_; }; + inline std::uint32_t TotalBits() { return totalBits_; } + void Reset(); + bool WriteStream(const std::uint8_t *data, std::uint32_t size); +private: + bool bFinish_{false}; + std::uint32_t size_; + std::uint8_t *data_; + std::uint32_t totalBits_{0}; + std::uint32_t seek_{0}; + std::uint32_t bytesTemp_{0}; + std::uint32_t currentBits_{0}; +}; + +void InvBits4(std::uint8_t& uChar) +{ + static std::uint8_t table[16] = {0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, 0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F}; + uChar = table[uChar]; +} + +void InvBits(std::uint8_t& uChar) +{ + std::uint8_t uH4 = uChar >> 4; + std::uint8_t uL4 = uChar & 0xFF; + InvBits4(uH4); + InvBits4(uL4); + uChar = uL4 << 4 | uH4; +} + +void CBitsWriter::WriteBits(std::uint32_t data, std::uint32_t numBits) +{ + do { + if (!numBits) { + break; + } + assert(numBits < 24); + const std::uint32_t maxBitCount = sizeof(bytesTemp_) * 8; + bytesTemp_ |= data << ((maxBitCount - currentBits_) - numBits) ; + currentBits_ += numBits; + while (currentBits_ >= 8) + { + std::uint8_t byte = (std::uint8_t)(bytesTemp_ >> (maxBitCount - 8)); + WriteByte(byte); + bytesTemp_ <<= 8; + currentBits_ -= 8; + } + totalBits_ += numBits; + + } while (0); +} + +void CBitsWriter::WriteByte(std::uint8_t uByte) +{ + if (seek_ < size_) + { + data_[seek_++] = uByte; + } + else { + throw EncoderError("encoding bits not bits buffer error"); + } +} + +void CBitsWriter::Finish() +{ + if(!bFinish_) + { + // fill bits for byte + if(currentBits_ > 0 && currentBits_ < 8) + { + unsigned int kMaxBits = sizeof(bytesTemp_) * 8 ; + unsigned char h8 = (unsigned char)(bytesTemp_ >> (kMaxBits - 8));//24 + totalBits_ += (8 - currentBits_); + WriteByte(h8); + } + currentBits_ = 0; + bytesTemp_ = 0; + bFinish_ = true; + seek_ = 0; + } +} + +std::uint8_t *CBitsWriter::GetBuffer() +{ + return data_; +} + +void CBitsWriter::Reset() +{ + seek_ = 0; + bFinish_ = false; + totalBits_ = 0; +} + +bool CBitsWriter::WriteStream(const std::uint8_t *data, std::uint32_t size) +{ + for (unsigned int i = 0; i < size; i++) + WriteByte(data[i]); + totalBits_ += size * 8; + return true; +} + +static uint8_t indexForU16(uint16_t index, uint32_t bytes, uint32_t len) +{ + uint8_t flags = 0; + flags |= (index > 255 ? SECTION_TAG_MASK : 0); + SECTION_SET_LENGTH_LEN_FLAG(flags, bytes); + if (bytes == 0) { + switch (len) { + case 1: + flags &= (~SECTION_VALUE_MASK); + break; + case 2: + flags |= 0x1; + break; + case 4: + flags |= 0x2; + break; + case 8: + flags |= 0x3; + break; + } + } + return flags; +} + +static uint32_t bytesForU32(uint32_t length) { + if (length == 1) { + return 0; + } + else if (length == 2) { + return 0; + } + else if (length == 4) { + return 0; + } + else if (length == 8) { + return 0; + } + else if (length < 0xff) { + return 1; + } + else if (length < 0xffff) { + return 2; + } + else { + return 4; + } +} + +static uint32_t GetFTLVLength(uint16_t flag, uint32_t length) { + return 1 + (flag > 255 ? 2 : 1) + bytesForU32(length) + length; +} + +fStream *Section::stream() { + return decoder_ ? decoder_->stream_ : nullptr; +} + +uint32_t Section::decodingValueFromBuffer(uint8_t *buffer, uint32_t remain, Value *pval) { + uint32_t total_bytes_read = 0; + do { + uint32_t bytes_read = 0; + uint32_t bytes_decoding = sizeof(uint8_t); + int8_t type = 0; + if (!(bytes_read = decodingFromBuffer(buffer, remain, (uint8_t *)&type, &bytes_decoding))) { + break; + } + total_bytes_read += bytes_read; + buffer += bytes_read; + remain -= bytes_read; + if (type < Value::Type::NIL && type > Value::Type::FUNC_INST) { + break; + } + switch (type) { + case Value::Type::CLASS_DESC: + { + int32_t payload = -1; + uint16_t u16_payload = 0; + bytes_decoding = sizeof(uint16_t); + if (!(bytes_read = decodingFromBuffer(buffer, remain, (uint8_t *)&u16_payload, &bytes_decoding))) { + break; + } + payload = u16_payload; + std::vector descs = decoder()->exec_state()->class_factory()->descs(); + if (payload < 0 || payload >= descs.size()) { + throw DecoderError("decoding value payload class desc error"); + break; + } + SetCDValue(pval, reinterpret_cast(descs[payload])); + LOGD("decoding class desc value:%i\n", payload); + total_bytes_read += bytes_read; + break; + } + case Value::Type::FUNC: + { + int32_t payload = -1; + uint16_t u16_payload = 0; + bytes_decoding = sizeof(uint16_t); + if (!(bytes_read = decodingFromBuffer(buffer, remain, (uint8_t *)&u16_payload, &bytes_decoding))) { + break; + } + payload = u16_payload; + if (payload < 0) { + throw DecoderError("decoding value payload function error"); + break; + } + FuncState *func_state = decoder()->exec_state()->func_state(); + if (payload == 0) { + pval->f = func_state; + } + else if (payload - 1 >= func_state->all_childrens().size()) { + throw DecoderError("decoding value payload function error"); + break; + } + else { + pval->f = func_state->all_childrens()[payload - 1]; + } + pval->type = Value::Type::FUNC; + LOGD("decoding function value:%i\n", payload); + total_bytes_read += bytes_read; + break; + } + case Value::Type::STRING: + { + int32_t payload = -1; + uint16_t u16_payload = 0; + bytes_decoding = sizeof(uint16_t); + if (!(bytes_read = decodingFromBuffer(buffer, remain, (uint8_t *)&u16_payload, &bytes_decoding))) { + break; + } + payload = u16_payload; + if (payload < 0) { + throw DecoderError("decoding value payload string error"); + break; + } + const std::vector>>& store = decoder()->exec_state()->string_table()->store(); + if (payload >= store.size()) { + throw DecoderError("decoding value payload string error"); + break; + } + pval->str = store[payload].second.get(); + LOGD("decoding string value:[%i] %s\n", payload, pval->str->c_str()); + pval->type = Value::Type::STRING; + total_bytes_read += bytes_read; + break; + } + case Value::Type::INT: + { + int32_t i32_payload = 0; + bytes_decoding = sizeof(int32_t); + if (!(bytes_read = decodingFromBuffer(buffer, remain, (uint8_t *)&i32_payload, &bytes_decoding))) { + break; + } + pval->i = i32_payload; + pval->type = Value::Type::INT; + LOGD("decoding int value:%i\n", (int32_t)pval->i); + total_bytes_read += bytes_read; + break; + } + case Value::Type::NUMBER: + { + bytes_decoding = sizeof(double); + if (!(bytes_read = decodingFromBuffer(buffer, remain, (uint8_t *)&pval->n, &bytes_decoding))) { + break; + } + pval->type = Value::Type::NUMBER; + LOGD("decoding number value:%f\n", pval->n); + total_bytes_read += bytes_read; + break; + } + case Value::Type::BOOL: + { + bytes_decoding = sizeof(uint8_t); + if (!(bytes_read = decodingFromBuffer(buffer, remain, (uint8_t *)&pval->b, &bytes_decoding))) { + break; + } + pval->type = Value::Type::BOOL; + LOGD("decoding bool value:%i\n", pval->b); + total_bytes_read += bytes_read; + break; + } + case Value::Type::ARRAY: + { + uint8_t item_size = 0; + bytes_decoding = sizeof(uint8_t); + if (!(bytes_read = decodingFromBuffer(buffer, remain, (uint8_t *)&item_size, &bytes_decoding))) { + break; + } + total_bytes_read += bytes_read; + buffer += bytes_read; + remain -= bytes_read; + ClassFactory *class_factory = decoder()->exec_state()->class_factory(); + Value array_value = class_factory->CreateArray(); + if (!item_size) { + break; + } + Array *array = ValueTo(&array_value); + for (int i = 0; i < item_size; i++) { + Value item; + if (!(bytes_read = decodingValueFromBuffer(buffer, remain, &item))) { + throw DecoderError("decoding array item payload error"); + break; + } + total_bytes_read += bytes_read; + buffer += bytes_read; + remain -= bytes_read; + array->items.push_back(item); + } + *pval = array_value; + LOGD("decoding array:%s\n", ArrayToString(array).c_str()); + break; + } + case Value::Type::TABLE: + { + uint8_t keys_size = 0; + bytes_decoding = sizeof(uint8_t); + if (!(bytes_read = decodingFromBuffer(buffer, remain, (uint8_t *)&keys_size, &bytes_decoding))) { + break; + } + total_bytes_read += bytes_read; + buffer += bytes_read; + remain -= bytes_read; + ClassFactory *class_factory = decoder()->exec_state()->class_factory(); + Value table_value = class_factory->CreateTable(); + if (!keys_size) { + break; + } + Table *table = ValueTo
(&table_value); + for (int i = 0; i < keys_size; i++) { + Value key; + if (!(bytes_read = decodingValueFromBuffer(buffer, remain, &key))) { + throw DecoderError("decoding table key payload error"); + break; + } + if (!IsString(&key)) { + throw DecoderError("decoding table key payload error"); + break; + } + total_bytes_read += bytes_read; + buffer += bytes_read; + remain -= bytes_read; + Value val; + if (!(bytes_read = decodingValueFromBuffer(buffer, remain, &val))) { + throw DecoderError("decoding table value payload error"); + break; + } + total_bytes_read += bytes_read; + buffer += bytes_read; + remain -= bytes_read; + table->map.insert(std::make_pair(CStringValue(&key), val)); + } + *pval = table_value; + LOGD("decoding table:%s\n", TableToString(table).c_str()); + break; + } + default: + throw EncoderError("decoding value type unkown error"); + break; + } + + } while (0); + + return total_bytes_read; +} + +uint32_t Section::encodingValueToBuffer(uint8_t *buffer, uint32_t buffer_len, Value *pval) { + uint32_t total_bytes_write = 0; + do { + uint32_t bytes_write = 0; + uint8_t type = ttype(pval); + if (!(bytes_write = encodingToBuffer(buffer, buffer_len, sizeof(uint8_t), &type))) { + break; + } + buffer += bytes_write; + buffer_len -= bytes_write; + total_bytes_write += bytes_write; + switch (type) { + case Value::Type::CLASS_DESC: + { + int32_t payload = -1; + std::vector descs = encoder_->exec_state()->class_factory()->descs(); + int index = 0; + for (auto desc : descs) { + if (pval->gc == reinterpret_cast(desc)) { + payload = index; + break; + } + index++; + } + if (payload < 0) { + throw EncoderError("encoder value class desc can't find error"); + break; + } + uint16_t u16_payload = static_cast(payload); + if (!(bytes_write = encodingToBuffer(buffer, buffer_len, sizeof(uint16_t), &u16_payload))) { + break; + } + LOGD("encoding class value:%i\n", payload); + total_bytes_write += bytes_write; + break; + } + case Value::Type::FUNC: + { + int32_t payload = -1; + FuncState *func_state = encoder_->exec_state()->func_state(); + if (func_state == pval->f) { + payload++; + } + else { + const std::vector &childrens = func_state->all_childrens(); + int index = 0; + for (auto &func : childrens) { + if (pval->f == func) { + payload = index + 1; + break; + } + index++; + } + } + if (payload < 0) { + throw EncoderError("encoder value function can't find error"); + break; + } + uint16_t u16_payload = static_cast(payload); + if (!(bytes_write = encodingToBuffer(buffer, buffer_len, sizeof(uint16_t), &u16_payload))) { + break; + } + LOGD("encoding function value:%i\n", payload); + total_bytes_write += bytes_write; + break; + } + case Value::Type::STRING: + { + int32_t payload = -1; + int index = 0; + StringTable *string_table = encoder_->exec_state()->string_table(); + for (auto &store : string_table->store() ) { + if (pval->str == store.second.get()) { + payload = index; + break; + } + index++; + } + if (payload < 0) { + throw EncoderError("encoder value string can't find error"); + break; + } + uint16_t u16_payload = static_cast(payload); + if (!(bytes_write = encodingToBuffer(buffer, buffer_len, sizeof(uint16_t), &u16_payload))) { + break; + } + LOGD("encoding string value:[%i] %s\n", payload, pval->str->c_str()); + total_bytes_write += bytes_write; + break; + } + case Value::Type::INT: + { + int32_t i32_payload = static_cast(pval->i); + if (!(bytes_write = encodingToBuffer(buffer, buffer_len, sizeof(int32_t), &i32_payload))) { + break; + } + LOGD("encoding int value:%i\n", (int32_t)pval->i); + total_bytes_write += bytes_write; + break; + } + case Value::Type::NUMBER: + { + if (!(bytes_write = encodingToBuffer(buffer, buffer_len, sizeof(double), &pval->n))) { + break; + } + LOGD("encoding int value:%f\n", pval->n); + total_bytes_write += bytes_write; + break; + } + case Value::Type::BOOL: + { + if (!(bytes_write = encodingToBuffer(buffer, buffer_len, sizeof(uint8_t), &pval->b))) { + break; + } + LOGD("encoding bool value:%i\n", pval->b); + total_bytes_write += bytes_write; + break; + } + case Value::Type::ARRAY: + { + Array *array = ValueTo(pval); + uint8_t items_size = static_cast(array->items.size()); + if (!(bytes_write = encodingToBuffer(buffer, buffer_len, sizeof(uint8_t), &items_size))) { + throw EncoderError("encoder array item size error"); + break; + } + buffer += bytes_write; + buffer_len -= bytes_write; + total_bytes_write += bytes_write; + for (auto &item : array->items) { + uint32_t length = GetValueLength(&item); + uint32_t bytes_write = Section::encodingValueToBuffer(buffer, buffer_len, &item); + if (bytes_write != length) { + throw EncoderError("encoding array payload error"); + break; + } + buffer += bytes_write; + buffer_len -= bytes_write; + total_bytes_write += bytes_write; + } + LOGD("encoding array:%s\n", ArrayToString(array).c_str()); + break; + } + case Value::Type::TABLE: + { + StringTable *string_table = encoder()->exec_state()->string_table(); + Table *table = ValueTo
(pval); + uint8_t keys_size = static_cast(table->map.size()); + if (!(bytes_write = encodingToBuffer(buffer, buffer_len, sizeof(uint8_t), &keys_size))) { + throw EncoderError("encoder table key size error"); + break; + } + buffer += bytes_write; + buffer_len -= bytes_write; + total_bytes_write += bytes_write; + for (auto &map : table->map) { + Value key(string_table->StringFromUTF8(map.first)); + Value val = map.second; + uint32_t length = GetValueLength(&key); + uint32_t bytes_write = Section::encodingValueToBuffer(buffer, buffer_len, &key); + if (bytes_write != length) { + throw EncoderError("encoding table key payload error"); + break; + } + buffer += bytes_write; + buffer_len -= bytes_write; + total_bytes_write += bytes_write; + length = GetValueLength(&val); + bytes_write = Section::encodingValueToBuffer(buffer, buffer_len, &val); + if (bytes_write != length) { + throw EncoderError("encoding table key value payload error"); + break; + } + buffer += bytes_write; + buffer_len -= bytes_write; + total_bytes_write += bytes_write; + } + LOGD("encoding table:%s\n", TableToString(table).c_str()); + break; + } + default: + throw EncoderError("encoder value type unkown error"); + break; + } + + } while (0); + + return total_bytes_write; +} + +uint32_t Section::decodingFromBuffer(uint8_t *src_buffer, uint32_t src_buffer_len, uint8_t *buffer, uint32_t *len) { + uint32_t bytes_reader = 0; + do { + if (!buffer || !len) { + break; + } + if (*len > src_buffer_len) { + break; + } + memcpy(buffer, src_buffer, *len); + bytes_reader = *len; + + } while (0); + + return bytes_reader; +} + +uint32_t Section::decodingFromBuffer(uint8_t *src_buffer, uint32_t src_buffer_len, uint16_t *target, uint8_t *buffer, uint32_t *len) { + + uint32_t bytes_reader = 0; + do { + uint32_t flags = src_buffer[0]; + uint32_t target_length = 0; + uint16_t target_value = 0; + uint32_t value_length_bytes = 0; + uint32_t value_length = 0; + if (SECTION_TEST_FLAG(flags, SECTION_EXT_MASK)) { + flags = *(uint32_t *)src_buffer; + } + // tag + if (SECTION_TEST_FLAG(flags, SECTION_TAG_MASK)) { + target_length = 2; + target_value = *(uint16_t *) (src_buffer + 1); + } + else { + target_length = 1; + target_value = *(src_buffer + 1); + } + // length + if (SECTION_TEST_FLAG(flags, SECTION_LEN_MASK)) { + value_length_bytes = ((flags & SECTION_LEN_MASK) >> SECTION_LEN_OFF); + switch (value_length_bytes) { + case 1: + value_length = *(src_buffer + 1 + target_length); + break; + case 2: + value_length = *(uint16_t *) (src_buffer + 1 + target_length); + break; + case 3: + value_length = *(uint32_t *) (src_buffer + 1 + target_length); + break; + } + } + else { + value_length_bytes = 0; + value_length = (flags & SECTION_VALUE_MASK) + 1; + if (value_length == 3) { + value_length = 4; + } + else if (value_length == 4) { + value_length = 8; + } + } + // value + // if no out buffer specified, just out put the tag, and return value length + if (target) { + *target = target_value; + } + bytes_reader += 1 + target_length + value_length_bytes; + if (buffer == NULL || value_length == 0 || *len == 0) { + if (len) { + *len = value_length_bytes; + } + break; + } + // copy value data + uint32_t buffer_length = *len; + *len = value_length; + if (buffer_length > value_length) { + buffer_length = value_length; + } + memcpy(buffer, src_buffer + 1 + target_length + value_length_bytes, buffer_length); + bytes_reader += buffer_length; + + } while (0); + + return bytes_reader; +} + +uint32_t Section::encodingToBuffer(uint8_t *dst_buffer, uint32_t dst_buffer_len, uint32_t len, void *buffer) +{ + uint32_t byte_write = 0; + do { + if (dst_buffer_len < len || !buffer) { + break; + } + memcpy(dst_buffer, buffer, len); + byte_write = len; + + } while (0); + + return byte_write; +} + +uint32_t Section::encodingToBuffer(uint8_t *dst_buffer, uint32_t dst_buffer_len, uint16_t index, uint32_t len, void *buffer) +{ + uint32_t byte_write = 0; + do { + uint32_t index_bytes = index > 255 ? 2 : 1; + uint32_t len_bytes = bytesForU32(len); + uint8_t flags = indexForU16(index, len_bytes, len); + if (dst_buffer_len < 1 + index_bytes + len_bytes + len) { + break; + } + *(uint8_t *)dst_buffer = flags; + dst_buffer = (uint8_t *)dst_buffer + 1; + if (index_bytes == 1) { + *(uint8_t *)dst_buffer = (uint8_t)index; + } + else { + *(uint16_t *)dst_buffer = (uint16_t)index; + } + dst_buffer = (uint8_t *)dst_buffer + index_bytes; + if (len_bytes) { + memcpy(dst_buffer, &len, len_bytes); + } + dst_buffer = (uint8_t *)dst_buffer + len_bytes; + memcpy(dst_buffer, buffer, len); + byte_write = 1 + index_bytes + len_bytes + len; + + } while (0); + + return byte_write; +} + +bool Section::encoding(uint16_t index, uint32_t len, void *buffer) { + bool finished = false; + do { + FILE *fout = encoder_->fout_; + if (!fout) { + throw EncoderError("encoder can't open file"); + break; + } + uint32_t index_bytes = index > 255 ? 2 : 1; + uint32_t len_bytes = bytesForU32(len); + uint8_t flags = indexForU16(index, len_bytes, len); + size_t bytes_encoder = sizeof(flags); + if (fwrite(&flags, 1, 1, fout) != bytes_encoder) { + throw EncoderError("encoder write flags error"); + break; + } + if (fwrite(&index, 1, index_bytes, fout) != index_bytes) { + throw EncoderError("encoder write flags error"); + break; + } + if (len_bytes > 0) { + if (fwrite(&len, 1, len_bytes, fout) != len_bytes) { + throw EncoderError("encoder write length error"); + break; + } + } + if (len > 0 && buffer) { + if (fwrite(buffer, 1, len, fout) != len) { + throw EncoderError("encoder write buffer error"); + break; + } + } + finished = true; + + } while (0); + + return finished; +} + +uint32_t Section::GetValueLength(Value *value) { + uint32_t length = sizeof(uint8_t); + switch (ttype(value)) { + case Value::Type::CLASS_DESC: + case Value::Type::FUNC: + case Value::Type::STRING: + { + length += sizeof(uint16_t); + break; + } + case Value::Type::INT: + { + length += sizeof(int32_t); + break; + } + case Value::Type::NUMBER: + { + length += sizeof(double); + break; + } + case Value::Type::BOOL: + { + length += sizeof(uint8_t); + break; + } + case Value::Type::ARRAY: + { + length += sizeof(uint8_t); + Array *array = ValueTo(value); + for (auto item : array->items) { + length += GetValueLength(&item); + } + break; + } + case Value::Type::TABLE: + { + StringTable *string_table = encoder()->exec_state()->string_table(); + length += sizeof(uint8_t); + Table *table = ValueTo
(value); + for (auto &map : table->map) { + Value key(string_table->StringFromUTF8(map.first)); + Value val = map.second; + length += GetValueLength(&key); + length += GetValueLength(&val); + } + break; + } + default: + throw EncoderError("encoder value type unkown error"); + break; + } + return length; +} + +uint32_t SectionHeader::size() { + return GetFTLVLength(kHeaderMagicCode, sizeof(uint32_t)) + GetFTLVLength(kHeaderVersion, sizeof(uint32_t)) + GetFTLVLength(kHeaderCompartibleVersion, sizeof(uint32_t)) + GetFTLVLength(kHeaderEncrypt, sizeof(uint32_t)); +} + +bool SectionHeader::encoding() { + bool finished = false; + do { + uint32_t size = this->size(); + if (!size) { + break; + } + if (!Section::encoding((uint16_t)ExecSection::EXEC_SECTION_HEADER, size)) { + break; + } + uint32_t magic_code = EXEC_BINARY_MAGIC_NUMBER; + if (!Section::encoding(kHeaderMagicCode, sizeof(uint32_t), &magic_code)) { + break; + } + uint32_t version = EXEC_BINARY_CURRENT_VERSION; + if (!Section::encoding(kHeaderVersion, sizeof(uint32_t), &version)) { + break; + } + uint32_t compartibleVersion = EXEC_BINARY_COMPATIBLE_VERSION; + if (!Section::encoding(kHeaderCompartibleVersion, sizeof(uint32_t), &compartibleVersion)) { + break; + } + uint32_t encrypt = EXEC_BINARY_ENCRYPT; + if (!Section::encoding(kHeaderEncrypt, sizeof(uint32_t), &encrypt)) { + break; + } + finished = true; + + } while (0); + + return finished; +} + +bool SectionHeader::decoding() { + bool finished = false; + do { + fStream *stream = Section::stream(); + if (!stream) { + break; + } + if (stream->Tell() < 0) { + break; + } + int64_t seek_end = stream->Tell() + length(); + do { + uint16_t target = 0; + uint32_t value_length = stream->ReadTarget(&target, NULL, NULL); + if (!value_length) { + throw EncoderError("decoding header target error"); + return false; + } + switch (target) { + case kHeaderMagicCode: + { + uint32_t magic_code = 0; + if (stream->Read(&magic_code, 1, value_length) != value_length || magic_code != EXEC_BINARY_MAGIC_NUMBER) { + throw EncoderError("decoding header target magic code error"); + } + break; + } + case kHeaderVersion: + { + if (stream->Read(&version_, 1, value_length) != value_length) { + throw EncoderError("decoding header target magic code error"); + } + break; + } + case kHeaderCompartibleVersion: + { + if (stream->Read(&compartible_version_, 1, value_length) != value_length) { + throw EncoderError("decoding header target compartible version error"); + } + if (version_ < compartible_version_) { + throw EncoderError("decoding header target current version didn't compartible"); + } + break; + } + case kHeaderEncrypt: + { + if (stream->Read(&encrypt_, 1, value_length) != value_length) { + throw EncoderError("decoding header target encrypt error"); + } + break; + } + default: { // skip this node + if (stream->Seek(value_length, SEEK_CUR) < 0) { + return false; + } + break; + } + } + if (stream->Tell() < 0) { + return false; + } + + } while (stream->Tell() < seek_end); + + finished = true; + + } while (0); + + return finished; +} + +uint32_t SectionString::size() { + ExecState *exec_state = encoder()->exec_state(); + StringTable *string_table = exec_state->string_table(); + ClassFactory *class_factory = exec_state->class_factory(); + std::vector descs = class_factory->descs(); + int32_t class_compile_index = static_cast(exec_state->class_compile_index()); + int32_t descs_size = static_cast(descs.size()) - class_compile_index; + if (descs_size > 0) { + // import decs string to table + for (int i = class_compile_index; i < descs.size(); i++) { + ClassDescriptor *desc = descs[i]; + uint32_t static_func_size = static_cast(desc->statics_->size()); + if (static_func_size > 0) { + for (int j = 0; j < static_func_size; j++) { + Value *func = desc->statics_->Find(j); + if (!func) { + continue; + } + for (auto &item : desc->statics_->map()) { + if (item.second == j) { + string_table->StringFromUTF8(item.first); + break; + } + } + } + } + uint32_t class_func_size = static_cast(desc->funcs_->size()); + if (class_func_size > 0) { + for (int j = 0; j < class_func_size; j++) { + Value *func = desc->funcs_->Find(j); + if (!func) { + continue; + } + for (auto &item : desc->funcs_->map()) { + if (item.second == j) { + string_table->StringFromUTF8(item.first); + break; + } + } + } + } + } + } + uint32_t size = 0; + const std::vector>> &store = string_table->store(); + int32_t string_compile_index = exec_state->string_compile_index(); + int32_t count = static_cast(store.size()) - string_compile_index; + if (count > 0) { + size += GetFTLVLength(kValueStringSize, sizeof(uint32_t)); + for (auto iter = store.begin() + string_compile_index; iter != store.end(); iter++) { + size += GetFTLVLength(kValueStringPayload, (uint32_t)iter->first.length()); + } + } + return size; +} + +bool SectionString::encoding() { + bool finished = false; + do { + uint32_t size = this->size(); + if (!size) { + finished = true; + break; + } + if (!Section::encoding((uint16_t)ExecSection::EXEC_SECTION_STRING, size)) { + break; + } + ExecState *exec_state = encoder()->exec_state(); + StringTable *string_table = exec_state->string_table(); + const std::vector>> &store = string_table->store(); + int32_t string_compile_index = exec_state->string_compile_index(); + int32_t count = static_cast(store.size()) - string_compile_index; + if (!Section::encoding(kValueStringSize, sizeof(uint32_t), &count)) { + break; + } + bool error = false; + int index = 0; + for (auto iter = store.begin() + string_compile_index; iter != store.end(); iter++) { + const char *pcstr = iter->first.c_str(); + uint32_t length = (uint32_t)iter->first.length(); + if (!Section::encoding(kValueStringPayload, length, (void *)pcstr)) { + error = true; + break; + } + index++; + LOGD("encoding string:[%i] %s\n", index, pcstr); + } + finished = !error; + + } while (0); + + return finished; +} + +bool SectionString::decoding() { + bool finished = false; + do { + fStream *stream = Section::stream(); + if (!stream) { + break; + } + if (stream->Tell() < 0) { + break; + } + uint16_t target = 0; + uint32_t string_count = 0; + uint32_t size = sizeof(uint32_t); + uint32_t readbytes = stream->ReadTarget(&target, (uint8_t *)&string_count, &size); + if (readbytes != size || target != kValueStringSize) { + throw EncoderError("decoding string count error"); + break; + } + if (!string_count) { + break; + } + StringTable *string_table = decoder()->exec_state()->string_table(); + int index = 0; + for (index = 0; index < string_count; index++) { + uint16_t vindex = 0; + uint32_t varlen = stream->ReadTarget(&vindex, NULL, NULL); + if (vindex != kValueStringPayload) { + break; + } + if (varlen == 0) { + std::string str = ""; + string_table->StringFromUTF8(str); + continue; + } + char *pstr = (char *)malloc(varlen + 1); + if (!pstr) { + break; + } + memset(pstr, 0, varlen + 1); + if (stream->Read(pstr, 1, varlen) != varlen) { + throw EncoderError("decoding string content error"); + } + string_table->StringFromUTF8(pstr); + LOGD("decoding string:%s\n", pstr); + free(pstr); + } + if (index != string_count) { + break; + } + finished = true; + + } while (0); + + return finished; +} + +uint32_t SectionData::size() { + ExecState *exec_state = encoder()->exec_state(); + ClassFactory *class_factory = exec_state->class_factory(); + std::vector constants = class_factory->constants(); + uint32_t data_size = static_cast(constants.size()); + uint32_t size = 0; + if (data_size > 0) { + size += GetFTLVLength(kValueDataSize, sizeof(uint32_t)); + uint32_t constants_length = 0; + for (auto constant : constants) { + constants_length += GetValueLength(&constant); + } + size += GetFTLVLength(kValueDataPayload, constants_length); + } + return size; +} + +bool SectionData::encoding() { + bool finished = false; + do { + uint32_t size = this->size(); + if (!size) { + finished = true; + break; + } + if (!Section::encoding((uint16_t)ExecSection::EXEC_SECTION_DATA, size)) { + break; + } + ExecState *exec_state = encoder()->exec_state(); + ClassFactory *class_factory = exec_state->class_factory(); + std::vector constants = class_factory->constants(); + uint32_t data_size = static_cast(constants.size()); + if (!Section::encoding(kValueDataSize, sizeof(uint32_t), &data_size)) { + break; + } + uint32_t payload_length = 0; + for (int i = 0; i < constants.size(); i++) { + payload_length += GetValueLength(&constants[i]); + } + uint8_t *buffer = (uint8_t *)malloc(payload_length); + if (!buffer) { + throw EncoderError("low memory error"); + break; + } + uint8_t *write_buffer = buffer; + uint32_t remain_length = payload_length; + for (int i = 0; i < constants.size(); i++) { + uint32_t length = GetValueLength(&constants[i]); + uint32_t bytes_write = Section::encodingValueToBuffer(write_buffer, remain_length, &constants[i]); + if (bytes_write != length) { + throw EncoderError("encoding data payload error"); + break; + } + remain_length -= bytes_write; + write_buffer += bytes_write; + } + if (remain_length) { + free(buffer); + throw EncoderError("encoding data payload error"); + break; + } + if (!Section::encoding(kValueDataPayload, payload_length, buffer)) { + free(buffer); + throw EncoderError("encoding data payload error"); + break; + } + free(buffer); + finished = true; + + } while (0); + + return finished; +} + +bool SectionData::decoding() { + bool finished = false; + do { + fStream *stream = Section::stream(); + if (!stream) { + break; + } + if (stream->Tell() < 0) { + break; + } + uint16_t target = 0; + uint32_t data_size = 0; + uint32_t size = sizeof(uint32_t); + uint32_t readbytes = stream->ReadTarget(&target, (uint8_t *)&data_size, &size); + if (readbytes != size || target != kValueDataSize) { + throw EncoderError("decoding data size error"); + break; + } + if (!data_size) { + break; + } + if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) { + throw DecoderError("decoding data payload error"); + break; + } + if (target != kValueDataPayload) { + throw DecoderError("decoding data payload target error"); + break; + } + uint8_t *buffer = (uint8_t *)malloc(readbytes); + if (!buffer) { + throw DecoderError("low memory error"); + break; + } + if (stream->Read(buffer, 1, readbytes) != readbytes) { + free(buffer); + throw DecoderError("decoding data payload error"); + break; + } + uint8_t *read_buffer = buffer; + uint32_t remain_length = readbytes; + uint32_t bytes_read = 0; + for (int i = 0; i < data_size; i++) { + Value data; + if (!(bytes_read = decodingValueFromBuffer(read_buffer, remain_length, &data))) { + throw DecoderError("decoding data payload error"); + break; + } + read_buffer += bytes_read; + remain_length -= bytes_read; + } + if (remain_length) { + free(buffer); + throw DecoderError("decoding array item payload error"); + break; + } + free(buffer); + finished = true; + + } while (0); + + return finished; +} + +uint32_t SectionFunction::GetInstructionsBytes(std::vector& instructions) { + uint32_t numBits = 0; + do { + if (!instructions.size()) { + break; + } + numBits += sizeof(uint32_t) * 8; + uint8_t half_bits_op_code = op_code_bits_ / 2; + int half_bits_op_code_value = pow(2, half_bits_op_code); + for (int i = 0; i < instructions.size(); i++) { + Instruction instruction = instructions[i]; + numBits += 1; + OPCode code = GET_OP_CODE(instruction); + numBits += code >= half_bits_op_code_value ? op_code_bits_ : half_bits_op_code; + int ops = OPUtil::ops(code); + if (code == OP_GOTO) { + long A = GET_ARG_Ax(instruction); + numBits += 1; + numBits += A > 2047 ? 24 : 12; + } + else if (code == OP_JMP) { + long A = GET_ARG_A(instruction); + long B = GET_ARG_Bx(instruction); + numBits += 1; + numBits += A > 15 ? 8 : 4; + numBits += 1; + numBits += B > 2047 ? 24 : 12; + } + else { + switch (ops) { + case 1: + { + long A = GET_ARG_Ax(instruction); + numBits += 1; + numBits += A > 15 ? 8 : 4; + if (A > SECTION_REGISTER_MAX) { + throw EncoderError("register overflow error, please decrease function body"); + } + break; + } + case 2: + { + long A = GET_ARG_A(instruction); + long B = GET_ARG_Bx(instruction); + numBits += 1; + numBits += A > 15 ? 8 : 4; + numBits += 1; + numBits += B > 15 ? 8 : 4; + if (A > SECTION_REGISTER_MAX || B > SECTION_REGISTER_MAX) { + throw EncoderError("register overflow error, please decrease function body"); + } + break; + } + case 3: + { + long A = GET_ARG_A(instruction); + long B = GET_ARG_B(instruction); + long C = GET_ARG_C(instruction); + numBits += 1; + numBits += A > 15 ? 8 : 4; + numBits += 1; + numBits += B > 15 ? 8 : 4; + numBits += 1; + numBits += C > 15 ? 8 : 4; + if (A > SECTION_REGISTER_MAX || B > SECTION_REGISTER_MAX || C > SECTION_REGISTER_MAX) + { + throw EncoderError("register overflow error, please decrease function body"); + } + break; + } + default: + break; + } + } + } + + } while (0); + + return (numBits + 7) / 8; +} + +uint32_t SectionFunction::decodingInstructionsFromBuffer(uint8_t *buffer, uint32_t bytes, std::vector& instructions) { + uint32_t bytes_reading = 0; + do { + CBitsReader reader(buffer, bytes); + uint32_t count = 0; + if (reader.readStream((uint8_t *)&count, sizeof(uint32_t)) != sizeof(uint32_t) || !count) { + throw DecoderError("decoding instructions buffer count zero error"); + break; + } + uint8_t half_bits_op_code = op_code_bits_ / 2; + for (int i = 0; i < count; i++) { + uint8_t using_full_bits_op_code = reader.nextBits(1); + uint32_t codeBits = reader.nextBits(using_full_bits_op_code ? op_code_bits_ : half_bits_op_code); + if (codeBits >= OP_INVALID) { + throw DecoderError("decoding instructions code error"); + break; + } + uint32_t A = 0, B = 0, C = 0; + uint8_t using8bits = 0, using24bits = 0; + OPCode code = static_cast(codeBits); + int ops = OPUtil::ops(code); + Instruction instruction; + if (code == OP_GOTO) { + using24bits = reader.nextBits(1); + A = reader.nextBits(using24bits ? 24 : 12); + instruction = CREATE_Ax(code, A); + } + else if (code == OP_JMP) { + using8bits = reader.nextBits(1); + A = reader.nextBits(using8bits ? 8 : 4); + using24bits = reader.nextBits(1); + B = reader.nextBits(using24bits ? 24 : 12); + instruction = CREATE_ABx(code, A, B); + } + else { + switch (ops) { + case 1: + { + using8bits = reader.nextBits(1); + A = reader.nextBits(using8bits ? 8 : 4); + instruction = CREATE_Ax(code, A); + break; + } + case 2: + { + using8bits = reader.nextBits(1); + A = reader.nextBits(using8bits ? 8 : 4); + using8bits = reader.nextBits(1); + B = reader.nextBits(using8bits ? 8 : 4); + instruction = CREATE_ABx(code, A, B); + break; + } + case 3: + { + using8bits = reader.nextBits(1); + A = reader.nextBits(using8bits ? 8 : 4); + using8bits = reader.nextBits(1); + B = reader.nextBits(using8bits ? 8 : 4); + using8bits = reader.nextBits(1); + C = reader.nextBits(using8bits ? 8 : 4); + instruction = CREATE_ABC(code, A, B, C); + break; + } + default: + instruction = CREATE_Ax(code, 0); + break; + } + } + LOGD("decoding Instructions:%ld\n", instruction); + instructions.push_back(instruction); + } + if (reader.remainingBytes()) { + throw DecoderError("decoding instructions code error"); + break; + } + bytes_reading = bytes; + + } while (0); + + return bytes_reading; +} + +uint32_t SectionFunction::encodingInstructionsToBuffer(uint8_t *buffer, uint32_t bytes, std::vector& instructions) { + uint32_t bytes_writed = 0; + do { + if (!instructions.size()) { + break; + } + CBitsWriter writer(buffer, bytes); + uint32_t count = static_cast(instructions.size()); + if (!writer.WriteStream((const uint8_t *)&count, sizeof(uint32_t))) { + throw EncoderError("write instructions size error"); + break; + } + uint8_t half_bits_op_code = op_code_bits_ / 2; + int half_bits_op_code_value = pow(2, half_bits_op_code); + for (int i = 0; i < count; i++) { + Instruction instruction = instructions[i]; + OPCode code = GET_OP_CODE(instruction); + std::uint32_t bits_data = code >= half_bits_op_code_value ? 1 : 0; + writer.WriteBits(bits_data, 1); + std::uint32_t numBits = bits_data ? op_code_bits_ : half_bits_op_code; + bits_data = code; + writer.WriteBits(bits_data, numBits); + int ops = OPUtil::ops(code); + bool using8bits = false; + bool using24bits = false; + if (code == OP_GOTO) { + long A = GET_ARG_Ax(instruction); + using24bits = A > 2047 ? true : false; + bits_data = using24bits ? 1 : 0; + writer.WriteBits(bits_data, 1); + bits_data = static_cast(A); + writer.WriteBits(bits_data, using24bits ? 24 : 12); + } + else if (code == OP_JMP) { + long A = GET_ARG_A(instruction); + long B = GET_ARG_Bx(instruction); + using8bits = A > 15 ? true : false; + bits_data = using8bits ? 1 : 0; + writer.WriteBits(bits_data, 1); + bits_data = static_cast(A); + writer.WriteBits(bits_data, using8bits ? 8 : 4); + using24bits = B > 2047 ? true : false; + bits_data = using24bits ? 1 : 0; + writer.WriteBits(bits_data, 1); + bits_data = static_cast(B); + writer.WriteBits(bits_data, using24bits ? 24 : 12); + } + else { + switch (ops) { + case 1: + { + long A = GET_ARG_Ax(instruction); + using8bits = A > 15 ? true : false; + bits_data = using8bits ? 1 : 0; + writer.WriteBits(bits_data, 1); + bits_data = static_cast(A); + writer.WriteBits(bits_data, using8bits ? 8 : 4); + break; + } + case 2: + { + long A = GET_ARG_A(instruction); + long B = GET_ARG_Bx(instruction); + using8bits = A > 15 ? true : false; + bits_data = using8bits ? 1 : 0; + writer.WriteBits(bits_data, 1); + bits_data = static_cast(A); + writer.WriteBits(bits_data, using8bits ? 8 : 4); + using8bits = B > 15 ? true : false; + bits_data = using8bits ? 1 : 0; + writer.WriteBits(bits_data, 1); + bits_data = static_cast(B); + writer.WriteBits(bits_data, using8bits ? 8 : 4); + break; + } + case 3: + { + long A = GET_ARG_A(instruction); + long B = GET_ARG_B(instruction); + long C = GET_ARG_C(instruction); + using8bits = A > 15 ? true : false; + bits_data = using8bits ? 1 : 0; + writer.WriteBits(bits_data, 1); + bits_data = static_cast(A); + writer.WriteBits(bits_data, using8bits ? 8 : 4); + using8bits = B > 15 ? true : false; + bits_data = using8bits ? 1 : 0; + writer.WriteBits(bits_data, 1); + bits_data = static_cast(B); + writer.WriteBits(bits_data, using8bits ? 8 : 4); + using8bits = C > 15 ? true : false; + bits_data = using8bits ? 1 : 0; + writer.WriteBits(bits_data, 1); + bits_data = static_cast(C); + writer.WriteBits(bits_data, using8bits ? 8 : 4); + break; + } + default: + break; + } + } + LOGD("encoding Instructions:%ld\n", instruction); + } + writer.Finish(); + LOGD("Writer Instructions: numBits:%i\n", (int)writer.TotalBits()); + if (writer.TotalBits() / 8 != bytes) { + throw EncoderError("encoding instructions buffer size error"); + break; + } + bytes_writed += bytes; + + } while (0); + + return bytes_writed; +} + +uint32_t SectionFunction::size() { + uint32_t size = 0; + std::vector func_states; + FuncState *func_state = encoder()->exec_state()->func_state(); + if (func_state) { + func_states.push_back(func_state); + } + std::vector childrens = func_state->all_childrens(); + for (auto &func : childrens) { + func_states.push_back(func); + } + uint32_t total_constancts_bytes = 0; + uint32_t total_instructions_bytes = 0; + if (func_states.size() > 0) { + size += GetFTLVLength(kValueFunctionSize, sizeof(uint32_t)); + for (auto &func_state : func_states) { + size += GetFTLVLength(kValueFunctionSuper, sizeof(int32_t)); + size += GetFTLVLength(kValueFunctionClass, sizeof(uint8_t)); + if (func_state->argc() > 0) { + size += GetFTLVLength(kValueFunctionArgs, sizeof(int32_t) * func_state->argc()); + } + if (func_state->in_closure().size() > 0) { + size += GetFTLVLength(kValueFunctionInClosure, sizeof(int32_t) * (uint32_t)func_state->in_closure().size()); + } + if (func_state->out_closure().size() > 0) { + size += GetFTLVLength(kValueFunctionOutClosure, sizeof(int32_t) * (uint32_t)func_state->out_closure().size()); + } + if (func_state->instructions().size() > 0) { + uint32_t instructions_bytes = GetInstructionsBytes(func_state->instructions()); + instructions_bytes = GetFTLVLength(kValueFunctionInstructions, instructions_bytes); + total_instructions_bytes += instructions_bytes; + size += instructions_bytes; + } + if (func_state->constants().size() > 0) { + size += GetFTLVLength(kValueFunctionConstantCount, sizeof(int32_t)); + uint32_t constant_bytes = 0; + for (int i = 0; i < func_state->constants().size(); i++) { + constant_bytes += GetValueLength(&func_state->constants()[i]); + } + constant_bytes = GetFTLVLength(kValueFunctionConstantPayload, constant_bytes); + total_constancts_bytes += constant_bytes; + size += constant_bytes; + } + size += GetFTLVLength(kValueFunctionFinished, sizeof(uint8_t)); + } + } + LOGD("[WXExecEncoder]: instructions:%.02f K\n", (double)total_instructions_bytes / 1024); + LOGD("[WXExecEncoder]: constancts:%.02f K\n", (double)total_constancts_bytes / 1024); + return size; +} + +bool SectionFunction::encoding() { + bool finished = false; + do { + uint32_t size = this->size(); + if (!size) { + finished = true; + break; + } + if (!Section::encoding((uint16_t)ExecSection::EXEC_SECTION_FUNCTION, size)) { + break; + } + std::vector func_states; + FuncState *func_state = encoder()->exec_state()->func_state(); + if (func_state) { + func_states.push_back(func_state); + } + std::vector childrens = func_state->all_childrens(); + for (auto &func : childrens) { + func_states.push_back(func); + } + uint32_t func_count = (uint32_t)func_states.size(); + if (!Section::encoding(kValueFunctionSize, sizeof(uint32_t), &func_count)) { + break; + } + for (int i = 0; i < func_count; i++) { + func_state = func_states[i]; + auto iter = std::find(func_states.begin(), func_states.end(), func_state->super_func()); + int32_t super_index = -1; + if (iter != func_states.end()) { + super_index = static_cast(iter - func_states.begin()); + } + else if (func_state->super_func()) { + throw EncoderError("can't find super function error"); + } + if (!Section::encoding(kValueFunctionSuper, sizeof(int32_t), &super_index)) { + break; + } + uint8_t is_class_func = func_state->is_class_func(); + if (!Section::encoding(kValueFunctionClass, sizeof(uint8_t), &is_class_func)) { + break; + } + if (func_state->argc() > 0) { + int32_t args[SECTION_FUNCTION_MAXARGS] = { 0 }; + assert(func_state->argc() == func_state->args().size()); + for (int i = 0; i < func_state->argc(); i++) { + args[i] = (int32_t)func_state->args()[i]; + } + if (!Section::encoding(kValueFunctionArgs, sizeof(int32_t) * func_state->argc(), args)) { + break; + } + } + if (func_state->in_closure().size() > 0) { + size_t size = sizeof(int32_t) * func_state->in_closure().size(); + int32_t *buffer = (int32_t *)malloc(size); + if (!buffer) { + throw EncoderError("low memory error"); + break; + } + memset(buffer, 0, size); + for (int i = 0; i < func_state->in_closure().size(); i++) { + buffer[i] = func_state->in_closure()[i]->ref_id(); + LOGD("encoding in_closure:%i\n", buffer[i]); + } + if (!Section::encoding(kValueFunctionInClosure, (uint32_t)size, buffer)) { + break; + } + free(buffer); + } + if (func_state->out_closure().size() > 0) { + size_t size = sizeof(int32_t) * func_state->out_closure().size(); + int32_t *buffer = (int32_t *)malloc(size); + if (!buffer) { + throw EncoderError("low memory error"); + break; + } + memset(buffer, 0, size); + for (int i = 0; i < func_state->out_closure().size(); i++) { + buffer[i] = func_state->out_closure()[i]->ref_id(); + LOGD("encoding out_closure:%i\n", buffer[i]); + } + if (!Section::encoding(kValueFunctionOutClosure, (uint32_t)size, buffer)) { + break; + } + free(buffer); + } + if (func_state->instructions().size() > 0) { + uint32_t instructions_bytes = GetInstructionsBytes(func_state->instructions()); + uint8_t *buffer = (uint8_t *)malloc(instructions_bytes); + if (!buffer) { + throw EncoderError("low memory error"); + break; + } + memset(buffer, 0, instructions_bytes); + if (encodingInstructionsToBuffer(buffer, instructions_bytes, func_state->instructions()) != instructions_bytes) { + LOGD("encoding instructions error\n"); + break; + } + if (!Section::encoding(kValueFunctionInstructions, (uint32_t)instructions_bytes, buffer)) { + break; + } + free(buffer); + } + if (func_state->constants().size() > 0) { + uint32_t constants_size = (uint32_t)func_state->constants().size(); + if (!Section::encoding(kValueFunctionConstantCount, sizeof(uint32_t), &constants_size)) { + break; + } + uint32_t constants_value_length = 0; + for (int i = 0; i < func_state->constants().size(); i++) { + constants_value_length += GetValueLength(&func_state->constants()[i]); + } + uint8_t *buffer = (uint8_t *)malloc(constants_value_length); + if (!buffer) { + throw EncoderError("low memory error"); + break; + } + uint8_t *write_buffer = buffer; + uint32_t remain_length = constants_value_length; + for (int i = 0; i < func_state->constants().size(); i++) { + uint32_t length = GetValueLength(&func_state->constants()[i]); + uint32_t bytes_write = Section::encodingValueToBuffer(write_buffer, remain_length, &func_state->constants()[i]); + if (bytes_write != length) { + throw EncoderError("encoding constants value error"); + break; + } + remain_length -= bytes_write; + write_buffer += bytes_write; + } + if (!Section::encoding(kValueFunctionConstantPayload, constants_value_length, buffer)) { + break; + } + free(buffer); + } + uint8_t function_finished = SECTION_VALUE_FINISHED; + if (!Section::encoding(kValueFunctionFinished, sizeof(uint8_t), &function_finished)) { + break; + } + } + finished = true; + + } while (0); + + return finished; +} + +bool SectionFunction::decoding() { + bool finished = false; + do { + fStream *stream = Section::stream(); + if (!stream) { + break; + } + if (stream->Tell() < 0) { + break; + } + int64_t seek_end = stream->Tell() + length(); + uint16_t target = 0; + uint32_t func_count = 0; + uint32_t size = sizeof(uint32_t); + uint32_t readbytes = stream->ReadTarget(&target, (uint8_t *)&func_count, &size); + if (!readbytes || target != kValueFunctionSize || !func_count) { + break; + } + std::vectorfunc_states; + for (int i = 0; i < func_count; i++) { + FuncState *func_state = new FuncState; + uint32_t constants_count = 0; + do { + if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) { + throw DecoderError("decoding read function target error"); + break; + } + switch (target) { + case kValueFunctionSuper: + { + int super_index = -1; + if (stream->Read(&super_index, 1, readbytes) != readbytes) { + throw DecoderError("decoding read super function error"); + } + func_state->set_super_index(super_index); + break; + } + case kValueFunctionClass: + { + uint8_t is_class_func = 0; + if (stream->Read(&is_class_func, 1, readbytes) != readbytes) { + throw DecoderError("decoding read class function error"); + } + func_state->set_is_class_func(is_class_func); + break; + } + case kValueFunctionArgs: + { + int32_t args[SECTION_FUNCTION_MAXARGS] = { 0 }; + int readcnt = readbytes / sizeof(int32_t); + if (stream->Read(args, sizeof(int32_t), readcnt) != readcnt) { + throw DecoderError("decoding read function args error"); + break; + } + for (int i = 0; i < readcnt; i++) { + func_state->args().push_back(args[i]); + } + func_state->argc() = readcnt; + break; + } + case kValueFunctionInstructions: + { + uint8_t *buffer = (uint8_t *)malloc(readbytes); + if (!buffer) { + throw DecoderError("decoding read function low memory error"); + break; + } + if (stream->Read(buffer, 1, readbytes) != readbytes) { + throw DecoderError("decoding read function instructions error"); + break; + } + if (decodingInstructionsFromBuffer(buffer, readbytes, func_state->instructions()) != readbytes) { + throw DecoderError("decoding read function instructions error"); + break; + } + free(buffer); + break; + } + case kValueFunctionConstantCount: + { + if (stream->Read(&constants_count, 1, readbytes) != readbytes) { + throw DecoderError("decoding read function constants count error"); + break; + } + break; + } + case kValueFunctionConstantPayload: + { + if (!constants_count) { + throw DecoderError("decoding read function constants count error"); + break; + } + uint8_t *buffer = (uint8_t *)malloc(readbytes); + if (!buffer) { + throw DecoderError("low memory error"); + break; + } + if (stream->Read(buffer, 1, readbytes) != readbytes) { + throw DecoderError("decoding function constants payload error"); + break; + } + uint8_t *read_buffer = buffer; + uint32_t remain_length = readbytes; + uint32_t bytes_read = 0; + for (int i = 0; i < constants_count; i++) { + Value value; + if (!(bytes_read = decodingValueFromBuffer(read_buffer, remain_length, &value))) { + throw DecoderError("decoding function constants payload error"); + break; + } + read_buffer += bytes_read; + remain_length -= bytes_read; + func_state->AddConstant(value); + } + free(buffer); + break; + } + case kValueFunctionOutClosure: + { + int32_t *buffer = (int32_t *)malloc(readbytes); + if (!buffer) { + throw DecoderError("decoding low memory error"); + break; + } + if (stream->Read(buffer, 1, readbytes) != readbytes) { + throw DecoderError("decoding function out closure error"); + break; + } + int32_t size = readbytes / sizeof(int32_t); + for (int i = 0; i < size; i++) { + func_state->out_closure_refs().push_back(buffer[i]); + LOGD("decoding function out closure:%i\n", buffer[i]); + } + break; + } + case kValueFunctionInClosure: + { + int32_t *buffer = (int32_t *)malloc(readbytes); + if (!buffer) { + throw DecoderError("decoding low memory error"); + break; + } + if (stream->Read(buffer, 1, readbytes) != readbytes) { + throw DecoderError("decoding function in closure error"); + break; + } + int32_t size = readbytes / sizeof(int32_t); + for (int i = 0; i < size; i++) { + func_state->in_closure_refs().push_back(buffer[i]); + LOGD("decoding function in closure:%i\n", buffer[i]); + } + break; + } + case kValueFunctionFinished: + { + uint8_t function_finshed = 0; + if (stream->Read(&function_finshed, 1, readbytes) != readbytes) { + throw DecoderError("decoding function finished error"); + break; + } + if (function_finshed != SECTION_VALUE_FINISHED) { + throw DecoderError("decoding function finished error"); + break; + } + break; + } + default: + { + if (stream->Seek(readbytes, SEEK_CUR) < 0) { + throw DecoderError("function decoding length error"); + } + break; + } + } + if (target == SECTION_VALUE_FINISHED) { + break; + } + + } while (stream->Tell() < seek_end); + + func_states.push_back(func_state); + } + if (!func_states.size()) { + break; + } + decoder()->exec_state()->reset(func_states[0]); + for (auto func : func_states) { + int index = func->super_index(); + if (index > -1) { + func_states[index]->AddChild(func); + } + } + finished = true; + + } while (0); + + return finished; +} + +uint32_t SectionGlobalConstants::size() { + uint32_t size = 0; + do { + Variables *global = encoder()->exec_state()->global(); + uint32_t compile_index = encoder()->exec_state()->global_compile_index(); + if (global->size() <= compile_index) { + break; + } + size += GetFTLVLength(kValueGlobalConstantsSize, sizeof(int32_t)); + uint32_t constant_length = 0; + for (uint32_t i = compile_index; i < global->size(); i++) { + Value *value = global->Find(compile_index); + constant_length += GetValueLength(value); + } + size += GetFTLVLength(kValueGlobalConstantsPayload, constant_length); + + } while (0); + + return size; +} + +bool SectionGlobalConstants::encoding() { + bool finished = false; + do { + uint32_t size = this->size(); + if (!size) { + finished = true; + break; + } + if (!Section::encoding((uint16_t)ExecSection::EXEC_SECTION_GLOBAL_CONSTANTS, size)) { + break; + } + Variables *global = encoder()->exec_state()->global(); + uint32_t compile_index = encoder()->exec_state()->global_compile_index(); + uint32_t constants_count = (uint32_t)(global->size() - compile_index); + if (!Section::encoding(kValueGlobalConstantsSize, sizeof(uint32_t), &constants_count)) { + break; + } + uint32_t constants_payload_length = 0; + for (int i = 0; i < constants_count; i++) { + Value *value = global->Find(compile_index + i); + constants_payload_length += GetValueLength(value); + } + uint8_t *buffer = (uint8_t *)malloc(constants_payload_length); + if (!buffer) { + throw EncoderError("low memory error"); + break; + } + uint8_t *write_buffer = buffer; + uint32_t remain_length = constants_payload_length; + for (int i = 0; i < constants_count; i++) { + Value *value = global->Find(compile_index + i); + uint32_t length = GetValueLength(value); + uint32_t bytes_write = Section::encodingValueToBuffer(write_buffer, remain_length, value); + if (bytes_write != length) { + throw EncoderError("encoding global constants value error"); + break; + } + remain_length -= bytes_write; + write_buffer += bytes_write; + } + if (!Section::encoding(kValueGlobalConstantsPayload, constants_payload_length, buffer)) { + break; + } + free(buffer); + finished = true; + + } while (0); + + return finished; +} + +bool SectionGlobalConstants::decoding() { + bool finished = false; + do { + fStream *stream = Section::stream(); + if (!stream) { + break; + } + if (stream->Tell() < 0) { + break; + } + uint16_t target = 0; + uint32_t constants_count = 0; + uint32_t size = sizeof(uint32_t); + uint32_t readbytes = stream->ReadTarget(&target, (uint8_t *)&constants_count, &size); + if (!readbytes || target != kValueGlobalConstantsSize || !constants_count) { + break; + } + if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) { + throw DecoderError("decoding global constants target error"); + break; + } + if (target != kValueGlobalConstantsPayload) { + break; + } + uint8_t *buffer = (uint8_t *)malloc(readbytes); + if (!buffer) { + throw DecoderError("low memory error"); + break; + } + if (stream->Read(buffer, 1, readbytes) != readbytes) { + throw DecoderError("decoding global constants payload error"); + break; + } + uint8_t *read_buffer = buffer; + uint32_t remain_length = readbytes; + uint32_t bytes_read = 0; + Variables *global = decoder()->exec_state()->global(); + if (global->IndexOf("__weex_data__") < 0) { + global->Set("__weex_data__", Value()); + } + if (global->IndexOf("_init_data") < 0) { + global->Set("_init_data", Value()); + } + for (int i = 0; i < constants_count; i++) { + Value value; + if (!(bytes_read = decodingValueFromBuffer(read_buffer, remain_length, &value))) { + throw DecoderError("decoding function constants payload error"); + break; + } + read_buffer += bytes_read; + remain_length -= bytes_read; + global->Add(value); + } + if (remain_length != 0) { + throw DecoderError("decoding function constants payload error"); + break; + } + free(buffer); + finished = true; + + } while (0); + + return finished; +} + +uint32_t SectionGlobalVariables::size() { + uint32_t size = 0; + do { + std::unordered_map global_variables = encoder()->exec_state()->global_variables(); + if (!global_variables.size()) { + break; + } + size += GetFTLVLength(kValueGlobalVariablesSize, sizeof(int32_t)); + for (auto variable : global_variables) { + uint32_t length = static_cast(variable.first.length()); + size += GetFTLVLength(kValueGlobalVariablesKey, length); + size += GetFTLVLength(kValueGlobalVariablesRegister, sizeof(int32_t)); + } + + } while (0); + + return size; +} + +bool SectionGlobalVariables::encoding() { + bool finished = false; + do { + uint32_t size = this->size(); + if (!size) { + finished = true; + break; + } + if (!Section::encoding((uint16_t)ExecSection::EXEC_SECTION_GLOBAL_VARIABLES, size)) { + break; + } + std::unordered_map global_variables = encoder()->exec_state()->global_variables(); + uint32_t global_variables_size = (uint32_t)global_variables.size(); + if (!Section::encoding(kValueGlobalVariablesSize, sizeof(uint32_t), &global_variables_size)) { + break; + } + for (auto variable : global_variables) { + uint32_t length = static_cast(variable.first.length()); + uint8_t *pstr = (uint8_t *)variable.first.c_str(); + if (!Section::encoding(kValueGlobalVariablesKey, length, pstr)) { + throw DecoderError("decoding global variables key error"); + break; + } + int32_t register_id = (int32_t)variable.second; + if (!Section::encoding(kValueGlobalVariablesRegister, sizeof(int32_t), ®ister_id)) { + throw DecoderError("decoding global variables register error"); + break; + } + } + finished = true; + + } while (0); + + return finished; +} + +bool SectionGlobalVariables::decoding() { + bool finished = false; + do { + fStream *stream = Section::stream(); + if (!stream) { + break; + } + if (stream->Tell() < 0) { + break; + } + uint16_t target = 0; + uint32_t global_variables_size = 0; + uint32_t size = sizeof(uint32_t); + uint32_t readbytes = stream->ReadTarget(&target, (uint8_t *)&global_variables_size, &size); + if (!readbytes || target != kValueGlobalVariablesSize || !global_variables_size) { + break; + } + std::unordered_map &global_variables = decoder()->exec_state()->global_variables(); + for (int i = 0; i < global_variables_size; i++) { + if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) { + throw DecoderError("decoding global variables target error"); + break; + } + if (target != kValueGlobalVariablesKey) { + throw DecoderError("decoding global variables target error"); + break; + } + char *pstr = (char *)malloc(readbytes + 1); + if (!pstr) { + throw DecoderError("decoding global variables low memory error"); + break; + } + memset(pstr, 0, readbytes + 1); + if (stream->Read(pstr, 1, readbytes) != readbytes) { + throw DecoderError("decoding global variables key error"); + break; + } + int32_t register_id = -1; + uint32_t size = sizeof(uint32_t); + readbytes = stream->ReadTarget(&target, (uint8_t *)®ister_id, &size); + if (readbytes != size || target != kValueGlobalVariablesRegister) { + throw EncoderError("decoding global variables register error"); + break; + } + global_variables.insert(std::pair(pstr, register_id)); + free(pstr); + } + finished = true; + + } while (0); + + return finished; +} + +uint32_t SectionStyles::size() { + uint32_t size = 0; + do { + std::map& styles = encoder()->exec_state()->context()->style_json(); + if (!styles.size()) { + break; + } + size += GetFTLVLength(kValueStyleSize, sizeof(uint32_t)); + for (auto style : styles) { + uint32_t key_length = (uint32_t)style.first.length(); + size += GetFTLVLength(kValueStyleKey, key_length); + const json11::Json::object& items = style.second.object_items(); + size += GetFTLVLength(kValueStyleItemSize, sizeof(uint32_t)); + for (auto iter = items.begin(); iter != items.end(); iter++) { + key_length = static_cast(iter->first.length()); + size += GetFTLVLength(kValueStyleKey, key_length); + uint32_t val_length = static_cast(iter->second.string_value().length()); + size += GetFTLVLength(kValueStyleValue, val_length); + } + } + + } while (0); + + return size; +} + +bool SectionStyles::encoding() { + bool finished = false; + do { + uint32_t size = this->size(); + if (!size) { + finished = true; + break; + } + if (!Section::encoding((uint16_t)ExecSection::EXEC_SECTION_STYLES, size)) { + break; + } + std::map& styles = encoder()->exec_state()->context()->style_json(); + uint32_t styles_size = (uint32_t)styles.size(); + if (!Section::encoding(kValueStyleSize, sizeof(uint32_t), &styles_size)) { + break; + } + for (auto style : styles) { + uint32_t length = (uint32_t)style.first.length(); + uint8_t *pstr = (uint8_t *)style.first.c_str(); + if (!Section::encoding(kValueStyleKey, length, pstr)) { + throw DecoderError("decoding style key error"); + break; + } + const json11::Json::object& items = style.second.object_items(); + uint32_t items_size = static_cast(items.size()); + if (!Section::encoding(kValueStyleItemSize, sizeof(uint32_t), &items_size)) { + throw DecoderError("decoding style items size error"); + break; + } + for (auto iter = items.begin(); iter != items.end(); iter++) { + uint32_t length = static_cast(iter->first.length()); + uint8_t *pstr = (uint8_t *)iter->first.c_str(); + if (!Section::encoding(kValueStyleKey, length, pstr)) { + throw DecoderError("decoding style item key error"); + break; + } + length = static_cast(iter->second.string_value().length()); + const char *pstr_val = iter->second.string_value().c_str(); + if (!Section::encoding(kValueStyleValue, length, (uint8_t *)pstr_val)) { + throw DecoderError("decoding style item value error"); + break; + } + } + } + finished = true; + + } while (0); + + return finished; +} + +bool SectionStyles::decoding() { + bool finished = false; + do { + fStream *stream = Section::stream(); + if (!stream) { + break; + } + if (stream->Tell() < 0) { + break; + } + std::map& styles = decoder()->exec_state()->context()->style_json(); + uint16_t target = 0; + uint32_t styles_size = 0; + uint32_t size = sizeof(uint32_t); + uint32_t readbytes = stream->ReadTarget(&target, (uint8_t *)&styles_size, &size); + if (!readbytes || target != kValueStyleSize || !styles_size) { + break; + } + for (uint32_t i = 0; i < styles_size; i++) { + if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) { + throw DecoderError("decoding styles target error"); + break; + } + if (target != kValueStyleKey) { + throw DecoderError("decoding styles target error"); + break; + } + char *pstr = (char *)malloc(readbytes + 1); + if (!pstr) { + throw DecoderError("decoding styles low memory error"); + break; + } + memset(pstr, 0, readbytes + 1); + if (stream->Read(pstr, 1, readbytes) != readbytes) { + throw DecoderError("decoding styles key error"); + break; + } + size = sizeof(uint32_t); + uint32_t items_size = 0; + readbytes = stream->ReadTarget(&target, (uint8_t *)&items_size, &size); + if (!readbytes || target != kValueStyleItemSize || !items_size) { + throw DecoderError("decoding styles items size error"); + break; + } + std::unordered_map items; + for (uint32_t j = 0; j < items_size; j++) { + if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) { + throw DecoderError("decoding styles target error"); + break; + } + if (target != kValueStyleKey) { + throw DecoderError("decoding styles target error"); + break; + } + char *pstr_key = (char *)malloc(readbytes + 1); + if (!pstr_key) { + throw DecoderError("decoding styles low memory error"); + break; + } + memset(pstr_key, 0, readbytes + 1); + if (stream->Read(pstr_key, 1, readbytes) != readbytes) { + throw DecoderError("decoding styles key error"); + break; + } + if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) { + throw DecoderError("decoding styles target error"); + break; + } + if (target != kValueStyleValue) { + throw DecoderError("decoding styles target error"); + break; + } + char *pstr_value = (char *)malloc(readbytes + 1); + if (!pstr_value) { + throw DecoderError("decoding styles low memory error"); + break; + } + memset(pstr_value, 0, readbytes + 1); + if (stream->Read(pstr_value, 1, readbytes) != readbytes) { + throw DecoderError("decoding styles key error"); + break; + } + json11::Json json(pstr_value); + items.insert(std::make_pair(pstr_key, json)); + free(pstr_key); + free(pstr_value); + } + json11::Json json(std::move(items)); + styles.insert(std::make_pair(pstr, std::move(json))); + free(pstr); + } + finished = true; + + } while (0); + + return finished; +} + +uint32_t SectionVaueRef::size() { + uint32_t size = 0; + do { + std::vector &refs = encoder()->exec_state()->refs(); + if (!refs.size()) { + break; + } + size += GetFTLVLength(kValueRefSize, sizeof(uint32_t)); + for (auto ref : refs) { + Value value; + value.type = Value::Type::FUNC; + value.f = ref->func_state(); + uint32_t func_state_length = GetValueLength(&value); + size += GetFTLVLength(kValueFuncState, func_state_length); + size += GetFTLVLength(kValueRegister, sizeof(int32_t)); + size += GetFTLVLength(kValueIsClosure, sizeof(uint8_t)); + size += GetFTLVLength(kValueRefFinished, sizeof(uint8_t)); + } + + } while (0); + + return size; +} + +bool SectionVaueRef::encoding() { + bool finished = false; + do { + uint32_t size = this->size(); + if (!size) { + finished = true; + break; + } + if (!Section::encoding((uint16_t)ExecSection::EXEC_SECTION_VALUEREF, size)) { + break; + } + std::vector &refs = encoder()->exec_state()->refs(); + uint32_t refs_size = (uint32_t)refs.size(); + if (!Section::encoding(kValueRefSize, sizeof(uint32_t), &refs_size)) { + break; + } + for (auto ref : refs) { + Value value; + value.type = Value::Type::FUNC; + value.f = ref->func_state(); + uint32_t length = GetValueLength(&value); + uint8_t *buffer = (uint8_t *)malloc(length); + if (!buffer) { + throw EncoderError("encoding low memory error"); + break; + } + uint32_t bytes_write = Section::encodingValueToBuffer(buffer, length, &value); + if (bytes_write != length) { + throw EncoderError("encoding ref value error"); + break; + } + if (!Section::encoding(kValueFuncState, length, buffer)) { + throw DecoderError("decoding ref value function state error"); + break; + } + free(buffer); + int32_t register_id = static_cast(ref->register_id()); + if (!Section::encoding(kValueRegister, sizeof(int32_t), ®ister_id)) { + throw DecoderError("decoding ref value register id error"); + break; + } + uint8_t is_closure = ref->is_closure(); + if (!Section::encoding(kValueIsClosure, sizeof(uint8_t), &is_closure)) { + throw DecoderError("decoding ref value is closure error"); + break; + } + uint8_t ref_finished = SECTION_VALUE_FINISHED; + if (!Section::encoding(kValueRefFinished, sizeof(uint8_t), &ref_finished)) { + throw DecoderError("decoding ref value finished error"); + break; + } + } + finished = true; + + } while (0); + + return finished; +} + +bool SectionVaueRef::decoding() { + bool finished = false; + do { + fStream *stream = Section::stream(); + if (!stream) { + break; + } + if (stream->Tell() < 0) { + break; + } + std::vector &refs = decoder()->exec_state()->refs(); + uint16_t target = 0; + uint32_t refs_size = 0; + uint32_t size = sizeof(uint32_t); + uint32_t readbytes = stream->ReadTarget(&target, (uint8_t *)&refs_size, &size); + if (!readbytes || target != kValueRefSize || !refs_size) { + break; + } + int64_t seek_end = stream->Tell() + length(); + ValueRef::reset(); + for (uint32_t i = 0; i < refs_size; i++) { + FuncState *func_state = nullptr; + ValueRef *ref = nullptr; + long register_id = -1; + do { + if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) { + throw DecoderError("decoding value ref target error"); + break; + } + switch (target) { + case kValueFuncState: + { + uint8_t *buffer = (uint8_t *)malloc(readbytes); + if (!buffer) { + throw DecoderError("low memory error"); + break; + } + if (stream->Read(buffer, 1, readbytes) != readbytes) { + throw DecoderError("decoding value ref function state error"); + break; + } + Value value; + if (!(readbytes = decodingValueFromBuffer(buffer, readbytes, &value))) + { + throw DecoderError("decoding value ref function state error"); + break; + } + if (value.type != Value::Type::FUNC || !value.f) { + throw DecoderError("decoding value ref function state error"); + break; + } + func_state = value.f; + break; + } + case kValueRegister: { + int32_t register_id_reader = -1; + if (stream->Read(®ister_id_reader, 1, readbytes) != readbytes) { + throw DecoderError("decoding value register id error"); + break; + } + if (register_id_reader < 0) { + throw DecoderError("decoding value register id error"); + } + register_id = register_id_reader; + if (func_state && register_id >= 0) { + ref = new ValueRef(func_state, register_id); + } + break; + } + case kValueIsClosure: + { + uint8_t is_closure = 0; + if (stream->Read(&is_closure, 1, readbytes) != readbytes) { + throw DecoderError("decoding value ref is closure error"); + break; + } + if (!ref) { + throw DecoderError("decoding value ref is closure error"); + } + ref->is_closure() = is_closure; + break; + } + case kValueRefFinished: + { + uint8_t finished = 0; + if (stream->Read(&finished, 1, readbytes) != readbytes) { + throw DecoderError("decoding value ref finished error"); + break; + } + if (finished != SECTION_VALUE_FINISHED) { + throw DecoderError("decoding value ref finished error"); + break; + } + break; + } + default: + { + if (stream->Seek(readbytes, SEEK_CUR) < 0) { + throw DecoderError("decoding value ref length error"); + } + break; + } + } + if (target == kValueRefFinished) { + break; + } + + } while (stream->Tell() < seek_end); + + if (ref) { + refs.push_back(ref); + } + } + std::vector func_states; + FuncState *func_state = decoder()->exec_state()->func_state(); + if (func_state) { + func_states.push_back(func_state); + } + std::vector childrens = func_state->all_childrens(); + for (auto &func : childrens) { + func_states.push_back(func); + } + for (auto &func : func_states) { + if (func->in_closure_refs().size() > 0) { + for (int i = 0; i < func->in_closure_refs().size(); i++) { + int32_t ref_id = func->in_closure_refs()[i]; + if (ref_id >= refs.size()) { + throw DecoderError("decoding value ref finder error"); + } + func->AddInClosure(refs[ref_id]); + } + } + if (func->out_closure_refs().size() > 0) { + for (int i = 0; i < func->out_closure_refs().size(); i++) { + int32_t ref_id = func->out_closure_refs()[i]; + if (ref_id >= refs.size()) { + throw DecoderError("decoding value ref finder error"); + } + func->AddOutClosure(refs[ref_id]); + } + } + } + finished = true; + + } while (0); + + return finished; +} + +uint32_t SectionClass::size() { + uint32_t size = 0; + do { + ExecState *exec_state = encoder()->exec_state(); + ClassFactory *class_factory = exec_state->class_factory(); + StringTable *string_table = exec_state->string_table(); + std::vector descs = class_factory->descs(); + int32_t class_compile_index = static_cast(exec_state->class_compile_index()); + int32_t descs_size = static_cast(descs.size()) - class_compile_index; + if (descs_size <= 0) { + break; + } + size += GetFTLVLength(kValueClassSize, sizeof(uint32_t)); + for (int i = class_compile_index; i < descs.size(); i++) { + ClassDescriptor *desc = descs[i]; + if (desc->p_super_) { + size += GetFTLVLength(kValueClassSuper, sizeof(int32_t)); + } + uint32_t static_func_size = static_cast(desc->statics_->size()); + if (static_func_size > 0) { + size += GetFTLVLength(kValueClassStaticFunctionSize, sizeof(uint32_t)); + uint32_t static_func_length = 0; + for (int j = 0; j < static_func_size; j++) { + Value *func = desc->statics_->Find(j); + if (!func) { + throw EncoderError("can't find class static funcs error"); + break; + } + static_func_length += GetValueLength(func); + static_func_length += GetFTLVLength(kValueClassFunctionKey, sizeof(uint8_t)); + for (auto &item : desc->statics_->map()) { + if (item.second == j) { + Value key(string_table->StringFromUTF8(item.first)); + static_func_length += GetValueLength(&key); + break; + } + } + } + size += GetFTLVLength(kValueClassStaticFunction, static_func_length); + } + uint32_t class_func_size = static_cast(desc->funcs_->size()); + if (class_func_size > 0) { + size += GetFTLVLength(kValueClassMemberFunctionSize, sizeof(uint32_t)); + uint32_t class_func_length = 0; + for (int j = 0; j < class_func_size; j++) { + Value *func = desc->funcs_->Find(j); + if (!func) { + throw EncoderError("can't find class funcs error"); + break; + } + class_func_length += GetValueLength(func); + class_func_length += GetFTLVLength(kValueClassFunctionKey, sizeof(uint8_t)); + for (auto &item : desc->funcs_->map()) { + if (item.second == j) { + Value key(string_table->StringFromUTF8(item.first)); + class_func_length += GetValueLength(&key); + break; + } + } + } + size += GetFTLVLength(kValueClassMemberFunction, class_func_length); + } + size += GetFTLVLength(kValueClassFinished, sizeof(uint8_t)); + } + + } while (0); + + return size; +} + +bool SectionClass::encoding() { + bool finished = false; + do { + uint32_t size = this->size(); + if (!size) { + finished = true; + break; + } + if (!Section::encoding((uint16_t)ExecSection::EXEC_SECTION_CLASS, size)) { + break; + } + ExecState *exec_state = encoder()->exec_state(); + ClassFactory *class_factory = exec_state->class_factory(); + StringTable *string_table = exec_state->string_table(); + std::vector descs = class_factory->descs(); + int32_t class_compile_index = static_cast(exec_state->class_compile_index()); + int32_t descs_size = static_cast(descs.size()) - class_compile_index; + if (descs_size <= 0) { + break; + } + if (!Section::encoding(kValueClassSize, sizeof(int32_t), &descs_size)) { + break; + } + for (int i = class_compile_index; i < descs.size(); i++) { + ClassDescriptor *desc = descs[i]; + if (desc->p_super_) { + int32_t super_index = class_factory->Find(desc->p_super_); + if (!Section::encoding(kValueClassSuper, sizeof(int32_t), &super_index)) { + break; + } + LOGD("encoding class super index:%i\n", super_index); + } + uint32_t static_func_size = static_cast(desc->statics_->size()); + if (static_func_size > 0) { + if (!Section::encoding(kValueClassStaticFunctionSize, sizeof(uint32_t), &static_func_size)) { + break; + } + LOGD("encoding class static function size:%d\n", static_func_size); + uint32_t static_func_length = 0; + for (int j = 0; j < static_func_size; j++) { + Value *func = desc->statics_->Find(j); + static_func_length += GetValueLength(func); + static_func_length += GetFTLVLength(kValueClassFunctionKey, sizeof(uint8_t)); + for (auto &item : desc->statics_->map()) { + if (item.second == j) { + Value key(string_table->StringFromUTF8(item.first)); + static_func_length += GetValueLength(&key); + break; + } + } + } + uint8_t *buffer = (uint8_t *)malloc(static_func_length); + if (!buffer) { + throw EncoderError("low memory error"); + break; + } + uint8_t *write_buffer = buffer; + uint32_t remain_length = static_func_length; + for (int j = 0; j < static_func_size; j++) { + Value *func = desc->statics_->Find(j); + uint32_t length = GetValueLength(func); + uint32_t bytes_write = Section::encodingValueToBuffer(write_buffer, remain_length, func); + if (bytes_write != length) { + throw EncoderError("encoding class static func value error"); + break; + } + write_buffer += bytes_write; + remain_length -= bytes_write; + uint8_t has_key_value = false; + Value key; + for (auto &item : desc->statics_->map()) { + if (item.second == j) { + LOGD("encoding class static function key:%s\n", item.first.c_str()); + key = Value(string_table->StringFromUTF8(item.first)); + has_key_value = true; + break; + } + } + if (!(bytes_write = Section::encodingToBuffer(write_buffer, remain_length, kValueClassFunctionKey, sizeof(uint8_t), &has_key_value))) { + break; + } + write_buffer += bytes_write; + remain_length -= bytes_write; + if (has_key_value) { + length = GetValueLength(&key); + bytes_write = Section::encodingValueToBuffer(write_buffer, remain_length, &key); + if (bytes_write != length) { + throw EncoderError("encoding class static func value error"); + break; + } + write_buffer += bytes_write; + remain_length -= bytes_write; + } + } + if (!Section::encoding(kValueClassStaticFunction, static_func_length, buffer)) { + break; + } + free(buffer); + } + uint32_t class_func_size = static_cast(desc->funcs_->size()); + if (class_func_size > 0) { + if (!Section::encoding(kValueClassMemberFunctionSize, sizeof(uint32_t), &class_func_size)) { + break; + } + LOGD("encoding class function size:%d\n", class_func_size); + uint32_t class_func_length = 0; + for (int j = 0; j < class_func_size; j++) { + Value *func = desc->funcs_->Find(j); + class_func_length += GetValueLength(func); + class_func_length += GetFTLVLength(kValueClassFunctionKey, sizeof(uint8_t)); + for (auto &item : desc->funcs_->map()) { + if (item.second == j) { + Value key(string_table->StringFromUTF8(item.first)); + class_func_length += GetValueLength(&key); + break; + } + } + } + uint8_t *buffer = (uint8_t *)malloc(class_func_length); + if (!buffer) { + throw EncoderError("low memory error"); + break; + } + uint8_t *write_buffer = buffer; + uint32_t remain_length = class_func_length; + for (int j = 0; j < class_func_size; j++) { + Value *func = desc->funcs_->Find(j); + uint32_t length = GetValueLength(func); + uint32_t bytes_write = Section::encodingValueToBuffer(write_buffer, remain_length, func); + if (bytes_write != length) { + throw EncoderError("encoding class func value error"); + break; + } + write_buffer += bytes_write; + remain_length -= bytes_write; + uint8_t has_key_value = false; + Value key; + for (auto &item : desc->funcs_->map()) { + if (item.second == j) { + key = Value(string_table->StringFromUTF8(item.first)); + has_key_value = true; + break; + } + } + if (!(bytes_write = Section::encodingToBuffer(write_buffer, remain_length, kValueClassFunctionKey, sizeof(uint8_t), &has_key_value))) { + break; + } + write_buffer += bytes_write; + remain_length -= bytes_write; + if (has_key_value) { + length = GetValueLength(&key); + bytes_write = Section::encodingValueToBuffer(write_buffer, remain_length, &key); + if (bytes_write != length) { + throw EncoderError("encoding class func value key error"); + break; + } + write_buffer += bytes_write; + remain_length -= bytes_write; + LOGD("encoding class function key:%s\n", key.str->c_str()); + } + } + if (!Section::encoding(kValueClassMemberFunction, class_func_length, buffer)) { + break; + } + free(buffer); + } + uint8_t class_finished = SECTION_VALUE_FINISHED; + if (!Section::encoding(kValueClassFinished, sizeof(uint8_t), &class_finished)) { + throw DecoderError("encoding class finished error"); + break; + } + } + finished = true; + + } while (0); + + return finished; +} + +bool SectionClass::decoding() { + bool finished = false; + do { + fStream *stream = Section::stream(); + if (!stream) { + break; + } + if (stream->Tell() < 0) { + break; + } + ClassFactory *class_factory = decoder()->exec_state()->class_factory(); + uint16_t target = 0; + uint32_t descs_size = 0; + uint32_t size = sizeof(uint32_t); + uint32_t readbytes = stream->ReadTarget(&target, (uint8_t *)&descs_size, &size); + if (!readbytes || target != kValueClassSize || !descs_size) { + break; + } + int64_t seek_end = stream->Tell() + length(); + std::vector descs = class_factory->descs(); + for (uint32_t i = 0; i < descs_size; i++) { + Value value = class_factory->CreateClassDescriptor(nullptr); + ClassDescriptor *desc = ValueTo(&value); + descs.push_back(desc); + uint32_t class_funcs_size = 0; + uint32_t class_static_funcs_size = 0; + do { + if ((readbytes = stream->ReadTarget(&target, NULL, NULL)) == 0) { + throw DecoderError("decoding class target error"); + break; + } + switch (target) { + case kValueClassSuper: { + int32_t super_index = -1; + if (stream->Read(&super_index, 1, readbytes) != readbytes) { + throw DecoderError("decoding class super error"); + break; + } + if (super_index < 0 || super_index >= descs.size()) { + throw DecoderError("decoding class super error"); + } + desc->p_super_ = descs[super_index]; + LOGD("decoding class super index:%i\n", super_index); + break; + } + case kValueClassStaticFunctionSize: + { + if (readbytes != sizeof(uint32_t)) { + throw DecoderError("decoding class static funcs size error"); + break; + } + if (stream->Read(&class_static_funcs_size, 1, readbytes) != readbytes) { + throw DecoderError("decoding class static funcs size error"); + break; + } + LOGD("decoding class static function size:%d\n", class_static_funcs_size); + break; + } + case kValueClassStaticFunction: + { + if (!class_static_funcs_size) { + throw DecoderError("decoding class static funcs size error"); + break; + } + uint8_t *buffer = (uint8_t *)malloc(readbytes); + if (!buffer) { + throw DecoderError("low memory error"); + break; + } + if (stream->Read(buffer, 1, readbytes) != readbytes) { + throw DecoderError("decoding class static func error"); + break; + } + uint8_t *read_buffer = buffer; + uint32_t remain_length = readbytes; + uint32_t bytes_read = 0; + for (int j = 0; j < class_static_funcs_size; j++) { + Value func, key; + if (!(bytes_read = decodingValueFromBuffer(read_buffer, remain_length, &func))) { + throw DecoderError("decoding class static func payload error"); + break; + } + read_buffer += bytes_read; + remain_length -= bytes_read; + uint8_t has_key_value = false; + uint32_t bytes_decoding = sizeof(uint8_t); + if (!(bytes_read = decodingFromBuffer(read_buffer, remain_length, &target, (uint8_t *)&has_key_value, &bytes_decoding))) { + break; + } + if (target != kValueClassFunctionKey) { + throw DecoderError("decoding class static func key error"); + break; + } + read_buffer += bytes_read; + remain_length -= bytes_read; + if (has_key_value) { + if (!(bytes_read = decodingValueFromBuffer(read_buffer, remain_length, &key))) { + throw DecoderError("decoding class static func key error"); + break; + } + read_buffer += bytes_read; + remain_length -= bytes_read; + if (!IsString(&key)) { + throw DecoderError("decoding class static func key error"); + break; + } + desc->statics_->Add(key.str->c_str(), func); + } + else { + desc->statics_->Add(func); + } + } + free(buffer); + break; + } + case kValueClassMemberFunctionSize: + { + if (readbytes != sizeof(uint32_t)) { + throw DecoderError("decoding class funcs size error"); + break; + } + if (stream->Read(&class_funcs_size, 1, readbytes) != readbytes) { + throw DecoderError("decoding class funcs size error"); + break; + } + LOGD("decoding class function size:%d\n", class_funcs_size); + break; + } + case kValueClassMemberFunction: + { + if (!class_funcs_size) { + throw DecoderError("decoding class funcs size error"); + break; + } + uint8_t *buffer = (uint8_t *)malloc(readbytes); + if (!buffer) { + throw DecoderError("low memory error"); + break; + } + if (stream->Read(buffer, 1, readbytes) != readbytes) { + throw DecoderError("decoding class func error"); + break; + } + uint8_t *read_buffer = buffer; + uint32_t remain_length = readbytes; + uint32_t bytes_read = 0; + for (int j = 0; j < class_funcs_size; j++) { + Value func, key; + if (!(bytes_read = decodingValueFromBuffer(read_buffer, remain_length, &func))) { + throw DecoderError("decoding class func payload error"); + break; + } + if (func.type != Value::Type::FUNC) { + throw DecoderError("decoding class func payload error"); + break; + } + read_buffer += bytes_read; + remain_length -= bytes_read; + uint8_t has_key_value = false; + uint32_t bytes_decoding = sizeof(uint8_t); + if (!(bytes_read = decodingFromBuffer(read_buffer, remain_length, &target, (uint8_t *)&has_key_value, &bytes_decoding))) { + break; + } + read_buffer += bytes_read; + remain_length -= bytes_read; + if (target != kValueClassFunctionKey) { + throw DecoderError("decoding class func key error"); + break; + } + if (has_key_value) { + if (!(bytes_read = decodingValueFromBuffer(read_buffer, remain_length, &key))) { + throw DecoderError("decoding class func key error"); + break; + } + if (!IsString(&key)) { + throw DecoderError("decoding class static func key error"); + break; + } + read_buffer += bytes_read; + remain_length -= bytes_read; + desc->funcs_->Add(key.str->c_str(), func); + } + else { + desc->funcs_->Add(func); + } + } + free(buffer); + break; + } + case kValueClassFinished: + { + uint8_t class_finshed = 0; + if (stream->Read(&class_finshed, 1, readbytes) != readbytes) { + throw DecoderError("decoding class finished error"); + break; + } + if (class_finshed != SECTION_VALUE_FINISHED) { + throw DecoderError("decoding class finished error"); + break; + } + break; + } + default: + { + if (stream->Seek(readbytes, SEEK_CUR) < 0) { + throw DecoderError("decoding value ref length error"); + } + break; + } + } + if (target == kValueClassFinished) { + break; + } + + } while (stream->Tell() < seek_end); + + } + finished = true; + + } while (0); + + return finished; +} + +} // namespace data_render +} // namespace core +} // namespace weex diff --git a/weex_core/Source/core/data_render/exec_state_section.h b/weex_core/Source/core/data_render/exec_state_section.h new file mode 100644 index 0000000000..1e1e3ceb52 --- /dev/null +++ b/weex_core/Source/core/data_render/exec_state_section.h @@ -0,0 +1,242 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CORE_DATA_RENDER_EXEC_STATE_SECTION_H +#define CORE_DATA_RENDER_EXEC_STATE_SECTION_H + +#include +#include +#include +#include "core/data_render/op_code.h" + +namespace weex { +namespace core { +namespace data_render { + +#define EXEC_BINARY_MAGIC_NUMBER 0x6d736100 +#define EXEC_BINARY_CURRENT_VERSION 6 +#define EXEC_BINARY_COMPATIBLE_VERSION 6 +#define EXEC_BINARY_ENCRYPT 0 + +enum ExecSection { + EXEC_SECTION_NONE = 0, + EXEC_SECTION_HEADER, + EXEC_SECTION_STRING, + EXEC_SECTION_DATA, + EXEC_SECTION_FUNCTION, + EXEC_SECTION_GLOBAL_CONSTANTS, + EXEC_SECTION_GLOBAL_VARIABLES, + EXEC_SECTION_STYLES, + EXEC_SECTION_VALUEREF, + EXEC_SECTION_CLASS +}; + +class fStream; +class ExecStateEncoder; +class ExecStateDecoder; +struct Value; + +class Section { +public: + explicit Section(ExecStateEncoder *encoder) : encoder_(encoder) {} + explicit Section(ExecStateDecoder *decoder, uint32_t length) : decoder_(decoder), length_(length) {} + virtual ~Section() {}; + bool encoding(uint16_t index, uint32_t len, void *buffer = nullptr); + uint32_t encodingToBuffer(uint8_t *dst_buffer, uint32_t dst_buffer_len, uint16_t index, uint32_t len, void *buffer = nullptr); + uint32_t encodingToBuffer(uint8_t *dst_buffer, uint32_t dst_buffer_len, uint32_t len, void *buffer); + uint32_t decodingFromBuffer(uint8_t *src_buffer, uint32_t src_buffer_len, uint16_t *index, uint8_t *buffer, uint32_t *len); + uint32_t decodingFromBuffer(uint8_t *src_buffer, uint32_t src_buffer_len, uint8_t *buffer, uint32_t *len); + uint32_t encodingValueToBuffer(uint8_t *buffer, uint32_t buffer_len, Value *pval); + uint32_t decodingValueFromBuffer(uint8_t *buffer, uint32_t buffer_len, Value *pval); + virtual bool encoding() { return false; }; + virtual bool decoding() { return false; }; + virtual uint32_t size() { return 0; }; + fStream *stream(); + inline uint32_t length() { return length_; } + uint32_t GetValueLength(Value *value); + inline ExecStateEncoder *encoder() { return encoder_; } + inline ExecStateDecoder *decoder() { return decoder_; } +private: + ExecStateEncoder *encoder_{nullptr}; + ExecStateDecoder *decoder_{nullptr}; + uint32_t length_{0}; +}; + +class SectionHeader : public Section { +public: + enum Header { + kHeaderMagicCode, + kHeaderVersion, + kHeaderCompartibleVersion, + kHeaderEncrypt, + }; + SectionHeader(ExecStateEncoder *encoder) : Section(encoder) {} + SectionHeader(ExecStateDecoder *decoder, uint32_t length) : Section(decoder, length) {} + virtual ~SectionHeader() {}; + virtual bool encoding(); + virtual bool decoding(); + virtual uint32_t size(); +private: + uint32_t version_{0}; + uint32_t compartible_version_{0}; + uint32_t encrypt_{0}; +}; + +class SectionString : public Section { +public: + enum SectionKey { + kValueStringSize, + kValueStringPayload, + }; + SectionString(ExecStateEncoder *encoder) : Section(encoder) {} + SectionString(ExecStateDecoder *decoder, uint32_t length) : Section(decoder, length) {} + virtual ~SectionString() {}; + virtual bool encoding(); + virtual bool decoding(); + virtual uint32_t size(); +}; + +class SectionData : public Section { +public: + enum SectionKey { + kValueDataSize, + kValueDataPayload + }; + SectionData(ExecStateEncoder *encoder) : Section(encoder) {} + SectionData(ExecStateDecoder *decoder, uint32_t length) : Section(decoder, length) {} + virtual ~SectionData() {}; + virtual bool encoding(); + virtual bool decoding(); + virtual uint32_t size(); +}; + +class SectionFunction : public Section { +public: + enum SectionKey { + kValueFunctionSize, + kValueFunctionSuper, + kValueFunctionClass, + kValueFunctionArgs, + kValueFunctionInClosure, + kValueFunctionOutClosure, + kValueFunctionInstructions, + kValueFunctionConstantCount, + kValueFunctionConstantPayload, + kValueFunctionFinished = 255, + }; + SectionFunction(ExecStateEncoder *encoder, uint8_t op_code_bits) : Section(encoder), op_code_bits_(op_code_bits) {} + SectionFunction(ExecStateDecoder *decoder, uint8_t op_code_bits, uint32_t length) : Section(decoder, length), op_code_bits_(op_code_bits) {} + uint32_t GetInstructionsBytes(std::vector& instructions); + uint32_t encodingInstructionsToBuffer(uint8_t *buffer, uint32_t bytes, std::vector& instructions); + uint32_t decodingInstructionsFromBuffer(uint8_t *buffer, uint32_t bytes, std::vector& instructions); + virtual ~SectionFunction() {}; + virtual bool encoding(); + virtual bool decoding(); + virtual uint32_t size(); +private: + uint8_t op_code_bits_{0}; +}; + +class SectionGlobalConstants : public Section { +public: + enum SectionKey { + kValueGlobalConstantsSize, + kValueGlobalConstantsPayload, + }; + SectionGlobalConstants(ExecStateEncoder *encoder) : Section(encoder) {} + SectionGlobalConstants(ExecStateDecoder *decoder, uint32_t length) : Section(decoder, length) {} + virtual ~SectionGlobalConstants() {}; + virtual bool encoding(); + virtual bool decoding(); + virtual uint32_t size(); +}; + +class SectionGlobalVariables: public Section { +public: + enum SectionKey { + kValueGlobalVariablesSize, + kValueGlobalVariablesKey, + kValueGlobalVariablesRegister + }; + SectionGlobalVariables(ExecStateEncoder *encoder) : Section(encoder) {} + SectionGlobalVariables(ExecStateDecoder *decoder, uint32_t length) : Section(decoder, length) {} + virtual ~SectionGlobalVariables() {}; + virtual bool encoding(); + virtual bool decoding(); + virtual uint32_t size(); +}; + +class SectionStyles: public Section { +public: + enum SectionKey { + kValueStyleSize, + kValueStyleKey, + kValueStyleValue, + kValueStyleItemSize, + }; + SectionStyles(ExecStateEncoder *encoder) : Section(encoder) {} + SectionStyles(ExecStateDecoder *decoder, uint32_t length) : Section(decoder, length) {} + virtual ~SectionStyles() {}; + virtual bool encoding(); + virtual bool decoding(); + virtual uint32_t size(); +}; + +class SectionVaueRef : public Section { +public: + enum SectionKey { + kValueRefSize, + kValueFuncState, + kValueIsClosure, + kValueRegister, + kValueRefFinished, + }; + SectionVaueRef(ExecStateEncoder *encoder) : Section(encoder) {} + SectionVaueRef(ExecStateDecoder *decoder, uint32_t length) : Section(decoder, length) {} + virtual ~SectionVaueRef() {}; + virtual bool encoding(); + virtual bool decoding(); + virtual uint32_t size(); +}; + +class SectionClass : public Section { +public: + enum SectionKey { + kValueClassSize, + kValueClassSuper, + kValueClassFunctionKey, + kValueClassStaticFunctionSize, + kValueClassStaticFunction, + kValueClassMemberFunctionSize, + kValueClassMemberFunction, + kValueClassFinished, + }; + SectionClass(ExecStateEncoder *encoder) : Section(encoder) {} + SectionClass(ExecStateDecoder *decoder, uint32_t length) : Section(decoder, length) {} + virtual ~SectionClass() {}; + virtual bool encoding(); + virtual bool decoding(); + virtual uint32_t size(); +}; + +} // namespace data_render +} // namespace core +} // namespace weex + +#endif // CORE_DATA_RENDER_EXEC_STATE_SECTION_H diff --git a/weex_core/Source/core/data_render/object.h b/weex_core/Source/core/data_render/object.h index 88671996b4..b551ca315a 100644 --- a/weex_core/Source/core/data_render/object.h +++ b/weex_core/Source/core/data_render/object.h @@ -52,6 +52,8 @@ class Frame; class ExecState; class FuncState; + +class FuncClosure; class String; @@ -59,8 +61,10 @@ class StringTable; class Value; +class ValueRef; + class Variables; - + typedef struct GCObject { CommonHeader; inline int decrement() { return --ref_; } @@ -91,12 +95,10 @@ struct Value { struct Value *ref {nullptr}; - enum Type { NIL, INT, NUMBER, BOOL, FUNC, CFUNC, STRING, CPTR, VALUE_REF, ARRAY, TABLE, CLASS_DESC, CLASS_INST }; + enum Type { NIL, INT, NUMBER, BOOL, FUNC, CFUNC, STRING, CPTR, VALUE_REF, ARRAY, TABLE, CLASS_DESC, CLASS_INST, FUNC_INST }; Type type; - int index = -1; - Value() : type(NIL) {} Value(int value) : i(value), type(INT) {} @@ -105,7 +107,7 @@ struct Value { Value(double value) : n(value), type(NUMBER) {} - Value(bool value) : b(value), type(BOOL) {} + explicit Value(bool value) : b(value), type(BOOL) {} Value(String *value) : str(value), type(STRING) {} @@ -113,7 +115,6 @@ struct Value { Value(const Value &value) { type = value.type; - index = value.index; switch (type) { case INT:i = value.i; break; @@ -135,6 +136,7 @@ struct Value { case ARRAY: case CLASS_DESC: case CLASS_INST: + case FUNC_INST: gc = value.gc; if(gc) gc->increment(); @@ -146,7 +148,6 @@ struct Value { inline Value operator=(Value value) { GCRelease(this); type = value.type; - index = value.index; switch (type) { case INT: i = value.i; @@ -176,6 +177,7 @@ struct Value { case ARRAY: case CLASS_DESC: case CLASS_INST: + case FUNC_INST: gc = value.gc; if(gc) gc->increment(); @@ -186,7 +188,6 @@ struct Value { } friend bool operator==(const Value &left, const Value &right) { if (left.type != right.type) return false; - if (left.index != right.index) return false; switch (left.type) { case NIL:return true; case INT:return left.i == right.i; @@ -200,6 +201,7 @@ struct Value { case TABLE: case CLASS_DESC: case CLASS_INST: + case FUNC_INST: return left.gc == right.gc; default:break; } @@ -223,7 +225,7 @@ typedef struct Table { Table() : map() {} } Table; - + class Variables { public: Value *Find(int index); @@ -232,14 +234,10 @@ class Variables { int Add(const std::string& name, Value value); int Set(const std::string& name, Value value); inline size_t size() {return values_.size();} - inline const std::map& map() {return map_;} - inline unsigned register_size() {return register_size_;} - void incrementRegisterSize() {register_size_++;} - + inline const std::map& map() { return map_; } private: std::map map_; std::vector values_; - unsigned register_size_ = 0; }; struct ClassDescriptor; @@ -247,10 +245,9 @@ struct ClassDescriptor; typedef struct ClassDescriptor { CommonHeader; ClassDescriptor *p_super_{nullptr}; - std::unique_ptr static_funcs_; + std::unique_ptr statics_; std::unique_ptr funcs_; - ClassDescriptor(ClassDescriptor *p_super) : p_super_(p_super), funcs_(new Variables), static_funcs_(new Variables), super_index_(-1) {} - int super_index_; + ClassDescriptor(ClassDescriptor *p_super) : p_super_(p_super), funcs_(new Variables), statics_(new Variables) {} } ClassDescriptor; typedef struct ClassInstance { @@ -261,6 +258,14 @@ typedef struct ClassInstance { ClassInstance(ClassDescriptor *p_desc) : p_desc_(p_desc), vars_(new Variables) {} } ClassInstance; + +typedef struct FuncInstance { + CommonHeader; + FuncState *func_{nullptr}; + std::vector closures_; + FuncInstance(FuncState *func) : func_(func), closures_() { } + +} FuncInstance; /* ** try to convert a value to an integer, rounding according to 'mode': @@ -348,7 +353,7 @@ inline int64_t ShiftLeft(const int64_t &a, const int64_t &b) { inline bool IsInt(const Value *o) { return Value::Type::INT == o->type; } -inline bool IsFunction(const Value *o) { return Value::Type::FUNC == o->type || Value::Type::CFUNC == o->type; } +inline bool IsFunction(const Value *o) { return Value::Type::FUNC == o->type || Value::Type::CFUNC == o->type || Value::Type::FUNC_INST == o->type; } inline bool IsPrototypeFunction(const Value *o) { return Value::Type::FUNC == o->type; } @@ -399,7 +404,7 @@ inline int IntMod(const int &a, const int &b) { return ret; } } - + inline bool IsNumber(const Value *o) { return Value::Type::NUMBER == o->type; } inline bool IsCptr(const Value *o) { return Value::Type::CPTR == o->type; } @@ -416,6 +421,8 @@ inline bool IsClass(const Value *o) { return nullptr != o && Value::Type::CLASS_ inline bool IsClassInstance(const Value *o) { return nullptr != o && Value::Type::CLASS_INST == o->type; } +inline bool IsFuncInstance(const Value *o) { return nullptr != o && Value::Type::FUNC_INST == o->type; } + inline int64_t IntValue(const Value *o) { return o->i; } inline double NumValue(const Value *o) { return o->n; } @@ -446,7 +453,7 @@ inline int ToNumber_(const Value *value, double &ret) { return 0; } } - + inline int ToNum(const Value *o, double &n) { return IsNumber(o) ? (static_cast(n = NumValue(o)), 1) : ToNumber_(o, n); } @@ -457,6 +464,7 @@ inline void SetIValue(Value *o, int iv) { o->i = iv; } + void SetRefValue(Value *o); inline void SetDValue(Value *o, double d) { @@ -499,6 +507,13 @@ inline void SetCIValue(Value *v, GCObject *o) { GCRetain(v); } +inline void SetGCFuncValue(Value *v, GCObject *o) { + GCRelease(v); + v->type = Value::Type::FUNC_INST; + v->gc = o; + GCRetain(v); +} + inline void SetSValue(Value *v, String *s) { GCRelease(v); v->type = Value::Type::STRING; @@ -557,7 +572,7 @@ inline int ToBool(const Value *o, bool &b) { b = NumValue(o); } else if (ttype(o) == Value::Type::STRING) { - b = o->str ? true : false; + b = (o->str && o->str->length() > 0) ? true : false; } else if (Value::Type::VALUE_REF == o->type) { return ToBool(o->var, b); diff --git a/weex_core/Source/core/data_render/op_code.cc b/weex_core/Source/core/data_render/op_code.cc new file mode 100644 index 0000000000..7b3f8949c5 --- /dev/null +++ b/weex_core/Source/core/data_render/op_code.cc @@ -0,0 +1,36 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "core/data_render/op_code.h" + +namespace weex { +namespace core { +namespace data_render { + +#define T(name, string, ops) #name, + const char *const OPUtil::s_name_[NUM_OPCODES] = {OP_CODE_LIST(T)}; +#undef T + +#define T(name, string, ops) ops, + const int8_t OPUtil::s_ops_[NUM_OPCODES] = {OP_CODE_LIST(T)}; +#undef T + +} // namespace data_render +} // namespace core +} // namespace weex diff --git a/weex_core/Source/core/data_render/op_code.h b/weex_core/Source/core/data_render/op_code.h index 9d74245373..a01f6f2714 100644 --- a/weex_core/Source/core/data_render/op_code.h +++ b/weex_core/Source/core/data_render/op_code.h @@ -19,73 +19,95 @@ #ifndef CORE_DATA_RENDER_OP_CODE_H_ #define CORE_DATA_RENDER_OP_CODE_H_ + +#include +#include + namespace weex { namespace core { namespace data_render { -enum OpCode { - OP_MOVE, // A B R(A) = R(B) - OP_LOADK, // A Bx R(A) = Constant[Bx] - OP_LOADNULL, // A R(A) = null - OP_GETGLOBAL, // A Bx R(A) = Global[B] - OP_GETFUNC, // A Bx R(A) = Function[B] - OP_NEW, - OP_GETCLASS, // A B C R(A) = B->C - OP_GETMEMBER, - OP_GETMEMBERVAR, - OP_SETMEMBERVAR, - OP_GETSUPER, // A B C R(A) = super[B] C = super func - - OP_SETOUTVAR, // A B C R(A) = B->C - OP_RESETOUTVAR, - OP_GETOUTVAR, // A B C R(A) = B->C - - OP_SETTABLE, // A B C R(A)[R(B)] = RK(C) - - OP_SETARRAY, // A B C R(A)[R(B)] = RK(C) - OP_GETINDEX, // A B C R(A) = R(B)[R(C)] - OP_GETINDEXVAR, - - OP_ADD, // A B C R(A) = R(B) + R(C) - OP_SUB, // A B C R(A) = R(B) - R(C) - OP_MUL, // A B C R(A) = R(B) * R(C) - OP_MOD, // A B C R(A) = R(B) % R(C) - OP_POW, // A B C R(A) = R(B) ^ R(C) - OP_DIV, // A B C R(A) = R(B) / R(C) - OP_IDIV, // A B C R(A) = R(B) // R(C) - OP_BAND, // A B C R(A) = R(B) & R(C) - OP_BOR, // A B C R(A) = R(B) | R(C) - OP_BXOR, // A B C R(A) = R(B) ~ R(C) - OP_SHL, // A B C R(A) = R(B) << R(C) - OP_SHR, // A B C R(A) = R(B) >> R(C) - OP_UNM, // A B R(A) = -R(B) - OP_BNOT, // A B R(A) = ~R(B) - - OP_JMP, // A Bx if (!R(A)) pc += Bx - OP_GOTO, // Ax pc = Ax - OP_EQ, // A B C R(A) = R(B) == R(C) - OP_SEQ, - OP_LT, // A B C R(A) = R(A) < R(B) - OP_LTE, - OP_GT, - OP_GTE, - OP_AND, - OP_OR, - OP_IN, - OP_NOT, - - OP_CALL, // A B C R(A) = R(B)(R(B+1), ... ,R(B+C-1)) - OP_RETURN0, // Return - OP_RETURN1, // Return R(A) - - OP_PRE_INCR, // A if (B >= 0) R(B) = ++R(A) else ++R(A) - OP_PRE_DECR, // A if (B >= 0) R(B) = --R(A) else --R(A) - - OP_POST_INCR, // A if (B >= 0) R(B) = R(A)++ else R(A)++ - OP_POST_DECR, // A if (B >= 0) R(B) = R(A)++ else R(A)-- - - OP_INVALID, - +#define OP_CODE_LIST(T) \ +T(OP_MOVE, "OP_MOVE", 2) \ +T(OP_SETTABLE, "OP_SETTABLE", 3) \ +T(OP_SETOUTVAR, "OP_SETOUTVAR", 2) \ +T(OP_LOADK, "OP_LOADK", 2) \ +T(OP_CALL, "OP_CALL", 3) \ +T(OP_GETMEMBER, "OP_GETMEMBER", 3) \ +T(OP_LOADNULL, "OP_LOADNULL", 1) \ +T(OP_GETGLOBAL, "OP_GETGLOBAL", 2) \ +T(OP_GETFUNC, "OP_GETFUNC", 2) \ +T(OP_NEW, "OP_NEW", 3) \ +T(OP_CONSTRUCTOR, "OP_CONSTRUCTOR", 3) \ +T(OP_GETCLASS, "OP_GETCLASS", 3) \ +T(OP_GETMEMBERVAR, "OP_GETMEMBERVAR", 3) \ +T(OP_SETMEMBERVAR, "OP_SETMEMBERVAR", 2) \ +T(OP_GETSUPER, "OP_GETSUPER", 3) \ +T(OP_RESETOUTVAR, "OP_RESETOUTVAR", 1) \ +T(OP_GETOUTVAR, "OP_GETOUTVAR", 2) \ +T(OP_OUT_CLOSURE, "OP_OUT_CLOSURE", 2) \ +T(OP_IN_CLOSURE, "OP_IN_CLOSURE", 2) \ +T(OP_REMOVE_CLOSURE, "OP_REMOVE_CLOSURE", 1) \ +T(OP_SETARRAY, "OP_SETARRAY", 3) \ +T(OP_GETINDEX, "OP_GETINDEX", 3) \ +T(OP_GETINDEXVAR, "OP_GETINDEXVAR", 3) \ +T(OP_TYPEOF, "OP_TYPEOF", 2) \ +T(OP_ADD, "OP_ADD", 3) \ +T(OP_SUB, "OP_SUB", 3) \ +T(OP_MUL, "OP_MUL", 3) \ +T(OP_MOD, "OP_MOD", 3) \ +T(OP_DIV, "OP_DIV", 3) \ +T(OP_JMP, "OP_JMP", 2) \ +T(OP_TRUE_JMP, "OP_TRUE_JMP", 2) \ +T(OP_JMPTO, "OP_JMPTO", 2) \ +T(OP_TRUE_JMPTO, "OP_TRUE_JMPTO", 2) \ +T(OP_GOTO, "OP_GOTO", 1) \ +T(OP_EQ, "OP_EQ", 3) \ +T(OP_SEQ, "OP_SEQ", 3) \ +T(OP_LT, "OP_LT", 3) \ +T(OP_LTE, "OP_LTE", 3) \ +T(OP_GT, "OP_GT", 3) \ +T(OP_GTE, "OP_GTE", 3) \ +T(OP_AND, "OP_AND", 3) \ +T(OP_OR, "OP_OR", 3) \ +T(OP_IN, "OP_IN", 3) \ +T(OP_NOT, "OP_NOT", 2) \ +T(OP_RETURN0, "OP_RETURN0", 0) \ +T(OP_RETURN1, "OP_RETURN1", 1) \ +T(OP_PREV_INCR, "OP_PREV_INCR", 2) \ +T(OP_PREV_DECR, "OP_PREV_DECR", 2) \ +T(OP_POST_INCR, "OP_POST_INCR", 2) \ +T(OP_POST_DECR, "OP_POST_DECR", 2) \ +T(OP_IDIV, "OP_IDIV", 3) \ +T(OP_POW, "OP_POW", 3) \ +T(OP_BAND, "OP_BAND", 3) \ +T(OP_BOR, "OP_BOR", 3) \ +T(OP_BXOR, "OP_BXOR", 3) \ +T(OP_SHL, "OP_SHL", 3) \ +T(OP_SHR, "OP_SHR", 3) \ +T(OP_UNM, "OP_UNM", 3) \ +T(OP_BNOT, "OP_BNOT", 3) \ +T(OP_INVALID, "OP_INVALID", 0) \ + +#define T(name, string, ops) name, + enum OPCode { + OP_CODE_LIST(T) NUM_OPCODES + }; +#undef T + +class OPUtil { +public: + static const char *name(OPCode code) { + assert(code < NUM_OPCODES); + return s_name_[code]; + } + static int ops(OPCode code) { + assert(code < NUM_OPCODES); // token is unsigned. + return s_ops_[code]; + } +private: + static const char *const s_name_[NUM_OPCODES]; + static const int8_t s_ops_[NUM_OPCODES]; }; typedef unsigned long Instruction; @@ -106,20 +128,20 @@ typedef unsigned long Instruction; #define CREATE_ABC(op_code, a, b, c) \ a < 0 || b < 0 || c < 0 \ - ? ((Instruction)OP_INVALID << POS_OP) \ +? ((Instruction)OP_INVALID << POS_OP) \ : ((Instruction)op_code << POS_OP) | ((Instruction)(a) << POS_A) | \ ((Instruction)(b) << POS_B) | ((Instruction)(c) << POS_C) #define CREATE_Ax(op_code, ax) \ - ax < 0 ? ((Instruction)OP_INVALID << POS_OP) \ +ax < 0 ? ((Instruction)OP_INVALID << POS_OP) \ : ((Instruction)op_code << POS_OP) | ((Instruction)(ax) << POS_Ax) #define CREATE_ABx(op_code, a, bx) \ - a < 0 || bx < 0 ? ((Instruction)OP_INVALID << POS_OP) \ +a < 0 || bx < 0 ? ((Instruction)OP_INVALID << POS_OP) \ : ((Instruction)op_code << POS_OP) | ((Instruction)(a) << POS_A) \ | ((Instruction)(bx) << POS_Bx) -#define GET_OP_CODE(i) (OpCode)(((i) >> POS_OP) & 0xFF) +#define GET_OP_CODE(i) (OPCode)(((i) >> POS_OP) & 0xFF) #define GET_ARG_A(i) (long)(((i) >> POS_A) & 0xFF) #define GET_ARG_B(i) (long)(((i) >> POS_B) & 0xFF) #define GET_ARG_C(i) (long)(((i) >> POS_C) & 0xFF) diff --git a/weex_core/Source/core/data_render/rax_jsx_ast.cc b/weex_core/Source/core/data_render/rax_jsx_ast.cc index 546c2b3d8c..b9eb802f43 100644 --- a/weex_core/Source/core/data_render/rax_jsx_ast.cc +++ b/weex_core/Source/core/data_render/rax_jsx_ast.cc @@ -53,7 +53,7 @@ std::vector>& JSXNodeExpression::funcexprs() { node_ptr_ = factory->NewStringConstant(vnode_ptr); } if (LowerIdentifier()) { - Handle vnode_index_expr = factory->NewIdentifier(JSX_GLOBAL_VNODE_INDEX); + Handle vnode_index_expr = factory->NewIdentifier(JS_GLOBAL_VNODE_INDEX); std::vector> args; Handle create_element_func_expr = factory->NewIdentifier("createElement"); args.push_back(factory->NewStringConstant(name)); @@ -71,18 +71,17 @@ std::vector>& JSXNodeExpression::funcexprs() { else if (is_class_) { std::string class_inst = vnode_ptr + "_inst"; funcexprs_.push_back(factory->NewDeclaration(vnode_ptr)); - funcexprs_.push_back(factory->NewDeclaration(class_inst, factory->NewNewExpression(identifier_))); + Handle argsList = factory->NewExpressionList(); // call constructor - std::vector> args; if (props_) { - args.push_back(props_); + argsList->Insert(props_); } else { ProxyObject proxy; - args.push_back(factory->NewObjectConstant(proxy)); + argsList->Insert(factory->NewObjectConstant(proxy)); } + funcexprs_.push_back(factory->NewDeclaration(class_inst, factory->NewNewExpression(identifier_, argsList))); Handle class_inst_expr = factory->NewIdentifier(class_inst); - funcexprs_.push_back(factory->NewCallExpression(MemberAccessKind::kCall, class_inst_expr, factory->NewIdentifier("constructor"), args)); // if (vnode_ptr.xxxx) then vnode_ptr.xxxx() Handle render_expr = factory->NewIdentifier("render"); Handle member_func_expr = factory->NewMemberExpression(MemberAccessKind::kClass, class_inst_expr, render_expr); @@ -112,19 +111,16 @@ std::vector>& JSXNodeExpression::funcexprs() { // if isClass { Handle class_inst_expr = factory->NewIdentifier(class_inst); - Handle new_expr = factory->NewNewExpression(identifier_); - new_expr->AsNewExpression()->set_is_class_(true); - if_then_stmts->Insert(factory->NewAssignExpression(class_inst_expr, new_expr)); - // call constructor - args.clear(); + Handle argsList = factory->NewExpressionList(); if (props_) { - args.push_back(props_); + argsList->Insert(props_); } else { ProxyObject proxy; - args.push_back(factory->NewObjectConstant(proxy)); + argsList->Insert(factory->NewObjectConstant(proxy)); } - if_then_stmts->Insert(factory->NewCallExpression(MemberAccessKind::kCall, class_inst_expr, factory->NewIdentifier("constructor"), args)); + Handle new_expr = factory->NewNewExpression(identifier_, argsList); + if_then_stmts->Insert(factory->NewAssignExpression(class_inst_expr, new_expr)); // if (vnode_ptr.xxxx) then vnode_ptr.xxxx() Handle render_expr = factory->NewIdentifier("render"); Handle member_func_expr = factory->NewMemberExpression(MemberAccessKind::kClass, class_inst_expr, render_expr); diff --git a/weex_core/Source/core/data_render/rax_jsx_ast.h b/weex_core/Source/core/data_render/rax_jsx_ast.h index 061fbcfb75..5b9b6a444e 100644 --- a/weex_core/Source/core/data_render/rax_jsx_ast.h +++ b/weex_core/Source/core/data_render/rax_jsx_ast.h @@ -29,10 +29,11 @@ namespace weex { namespace core { namespace data_render { -#define JSX_GLOBAL_VNODE_INDEX "global_vnode_index" -#define JS_GLOBAL_ARGUMENTS "__arguments" +#define JS_GLOBAL_VNODE_INDEX "global_vnode_index" +#define JS_GLOBAL_ARGUMENTS "arguments" +#define JS_GLOBAL_CONSTRUCTOR "constructor" +#define JS_GLOBAL_SUPER "super" - class JSXNodeExpression : public Expression { public: JSXNodeExpression(Position &loc, Scope *scope, Handle identifier, Handle props, Handle parent, std::vector> childrens) diff --git a/weex_core/Source/core/data_render/rax_parser.cc b/weex_core/Source/core/data_render/rax_parser.cc index b9ea584916..914878a289 100644 --- a/weex_core/Source/core/data_render/rax_parser.cc +++ b/weex_core/Source/core/data_render/rax_parser.cc @@ -218,6 +218,8 @@ PrefixOperation MapTokenWithPrefixOperator(Token& tok) { return PrefixOperation::kNot; case Token::UNFOLD: return PrefixOperation::kUnfold; + case Token::TYPEOF: + return PrefixOperation::kTypeof; default: LOGE("error prefix opration: %s", tok.view().c_str()); } @@ -323,8 +325,18 @@ Handle RAXParser::ParseUnaryExpression() } else if (tok == Token::ARROW_FUNCTION) { Advance(); - auto body = ParseStatement(); - return builder()->NewArrowFunctionStatement(body, {left}); + Handle body; + if(Peek() == Token::LBRACE){ + body = ParseStatement(); + } else{ + body = ParseExpression(); + } + if (left) { + return builder()->NewArrowFunctionStatement(body, {left}); + } + else { + return builder()->NewArrowFunctionStatement(body, {}); + } } else { return left; @@ -443,8 +455,7 @@ Handle RAXParser::ParsePrimary() throw SyntaxError(lex()->CurrentToken(), "can't support template"); } else if (tok == Token::REGEXP_LITERAL) { - // can't support - throw SyntaxError(lex()->CurrentToken(), "can't support regexp"); + result = builder()->NewRegexConstant(lex()->CurrentToken().view()); } else if (tok == Token::STRING) { result = builder()->NewStringConstant(lex()->CurrentToken().view()); @@ -466,7 +477,10 @@ Handle RAXParser::ParsePrimary() } else if (tok == Token::LPAREN) { Advance(); // eat '(' - result = ParseCommaExpression(); + tok = Peek(); + if (tok != Token::RPAREN) { + result = ParseCommaExpression(); + } tok = Peek(); if (tok != Token::RPAREN) { throw SyntaxError(lex()->CurrentToken(), "expected a ')'"); @@ -554,13 +568,13 @@ Handle RAXParser::ParseObjectConstant() Handle unfold_expr = ParseAssignExpression(); if (Peek() == Token::COMMA) { spread_property.push_back(unfold_expr); - orders.push_back(std::make_pair(ProxyOrder::ProxyArray, to_string((int)spread_property.size() - 1))); + orders.push_back(std::make_pair(ProxyOrder::ProxyArray, base::to_string((int)spread_property.size() - 1))); Advance(); continue; } else if (spread_property.size() > 0) { spread_property.push_back(unfold_expr); - orders.push_back(std::make_pair(ProxyOrder::ProxyArray, to_string((int)spread_property.size() - 1))); + orders.push_back(std::make_pair(ProxyOrder::ProxyArray, base::to_string((int)spread_property.size() - 1))); break; } return unfold_expr; @@ -712,7 +726,17 @@ Handle RAXParser::ParseReturnStatement() return builder()->NewReturnStatement(nullptr); } if (tok == Token::LPAREN) { - auto stmt = builder()->NewReturnStatement(ParseJSXNodeStatement()); + Advance(); + tok = Peek(); + Handle content; + if (tok == Token::LT) { + content = ParseJSXNodeStatement(); + } + else { + content = ParseExpression(); + } + EXPECT(Token::RPAREN); // eat ')' + auto stmt = builder()->NewReturnStatement(content); EXPECT(Token::SEMICOLON); return stmt; } @@ -844,7 +868,9 @@ Handle RAXParser::ParseJSXNodeStatement() { throw SyntaxError(lex()->CurrentToken(), "expected a identifier name"); } Handleexpr = ParseJSXNodeExpression(); - EXPECT(Token::GT); // eat '>' + if (Peek() == Token::JSX_TAG_END || Peek() == Token::GT) { + Advance(); // eat '>' or '/>' + } if (tok == Token::LPAREN && Peek() == Token::RPAREN) { Advance(); // eat ')' } @@ -870,14 +896,14 @@ Handle RAXParser::ParseJSXNodeProperty() { else if (tok == Token::UNFOLD) { Handle unfold_expr = ParseAssignExpression(); spread_property.push_back(unfold_expr); - orders.push_back(std::make_pair(ProxyOrder::ProxyArray, to_string((int)spread_property.size() - 1))); + orders.push_back(std::make_pair(ProxyOrder::ProxyArray, base::to_string((int)spread_property.size() - 1))); continue; } else if (tok == Token::RBRACE || tok == Token::LBRACE) { Advance(); continue; } - else if (tok == Token::DIV) { + else if (tok == Token::JSX_TAG_END) { break; } else { @@ -926,39 +952,67 @@ Handle RAXParser::ParseJSXNodeExpression(Handle parent) } else if (tok == Token::IDENTIFIER) { // props process + std::vector> orders; + ProxyArray spread_property; ProxyObject proxyObj; while (true) { auto token = Peek(); - if (token == Token::DIV || token == Token::GT) { + if (token == Token::JSX_TAG_END || token == Token::GT) { break; } - std::string key = GetIdentifierName(); - Advance(); - EXPECT(Token::ASSIGN); + std::string key; + if (token == Token::IDENTIFIER) { + while (Peek() == Token::SUB || Peek() == Token::IDENTIFIER) { + key += lex_->CurrentToken().view(); + Advance(); + } + EXPECT(Token::ASSIGN); + } if (Peek() == Token::LBRACE) { - EXPECT(Token::LBRACE); - proxyObj.insert(std::make_pair(key, ParseExpression())); - EXPECT(Token::RBRACE); + if (key.length() > 0) { + EXPECT(Token::LBRACE); + proxyObj.insert(std::make_pair(key, ParseAssignExpression())); + orders.push_back(std::make_pair(ProxyOrder::ProxyObject, key)); + EXPECT(Token::RBRACE); + } + else { + Advance(); + token = Peek(); + if (token == Token::UNFOLD) { + Handle unfold_expr = ParseAssignExpression(); + spread_property.push_back(unfold_expr); + orders.push_back(std::make_pair(ProxyOrder::ProxyArray, base::to_string((int)spread_property.size() - 1))); + } + EXPECT(Token::RBRACE); + continue; + } } else { std::string value = GetIdentifierName(); EXPECT(Token::STRING); proxyObj.insert(std::make_pair(key, builder()->NewStringConstant(value))); + orders.push_back(std::make_pair(ProxyOrder::ProxyObject, key)); } } props = builder()->NewObjectConstant(proxyObj); + if (spread_property.size() > 0) { + for (int i = 0; i < spread_property.size(); i++) { + props->AsObjectConstant()->SpreadProperty().push_back(spread_property[i]); + } + props->AsObjectConstant()->Orders() = orders; + } } tok = Peek(); expr = builder()->NewJSXNodeExpression(builder()->NewIdentifier(name), props, parent, {}); - if (tok == Token::DIV) { + if (tok == Token::JSX_TAG_END) { // no childrens - Advance(); // eat '/' +// Advance(); // eat '/' } else if (tok == Token::GT) { Advance(); while (true) { tok = Peek(); - if (tok != Token::LBRACE && tok != Token::LT && tok != Token::STRING && tok != Token::IDENTIFIER) { + if (tok != Token::LBRACE && tok != Token::LT && tok != Token::JSX_TAG_CLOSE && tok != Token::STRING && tok != Token::IDENTIFIER) { throw SyntaxError(lex()->CurrentToken(), "expected a string name"); break; } @@ -981,25 +1035,85 @@ Handle RAXParser::ParseJSXNodeExpression(Handle parent) if (tok == Token::IDENTIFIER) { Handle children = ParseJSXNodeExpression(expr); expr->AsJSXNodeExpression()->childrens().push_back(children); - EXPECT(Token::GT); // eat '>' - } - else if (tok == Token::DIV) { - Advance(); - auto tok = Peek(); - if (tok != Token::IDENTIFIER) { - throw SyntaxError(lex()->CurrentToken(), "expected a identifier name"); + if (Peek() == Token::JSX_TAG_END || Peek() == Token::GT) { + Advance(); // eat '>' or '/>' } - if (name != GetIdentifierName()) { - throw SyntaxError(lex()->CurrentToken(), "expected identifier name not equal"); - } - Advance(); // eat 'Identifier' - break; } + } else if(tok == Token::JSX_TAG_CLOSE){ + Advance(); + auto tok = Peek(); + if (tok != Token::IDENTIFIER) { + throw SyntaxError(lex()->CurrentToken(), "expected a identifier name"); + } + if (name != GetIdentifierName()) { + throw SyntaxError(lex()->CurrentToken(), "expected identifier name not equal"); + } + Advance(); // eat 'Identifier' + break; } } } return expr; } + +Handle RAXParser::ParseSwitchStatement() +{ + Advance(); + EXPECT(Token::LPAREN); + + Handle expr = ParseAssignExpression(); + EXPECT(Token::RPAREN); + EXPECT(Token::LBRACE); + + bool has_default = false; + std::vector> list; + while (true) { + Handle temp = nullptr; + if (Peek() == Token::CASE) { + Handle tempList = ParseCaseBlock(); + + list.push_back(tempList); + } else if (Peek() == Token::DEFAULT) { + if (has_default) { + throw SyntaxError(lex()->CurrentToken(),"switch statement has already has one default case"); + } + Handle tempList = ParseCaseBlock(true); + has_default = true; + list.push_back(tempList); + } else if (Peek() != Token::RBRACE) { + throw SyntaxError(lex()->CurrentToken(), "expected a '}'"); + } else { + Advance(); + break; + } + } + + return builder()->NewSwitchStatement(expr, list); +} + +Handle RAXParser::ParseCaseBlock(bool is_default) { + Advance(); + + Handle clause; + if (!is_default) { + clause = ParseAssignExpression(); + } + EXPECT(Token::COLON); + + Handle list = builder()->NewExpressionList(); + + if (Peek() != Token::CASE && Peek() != Token::DEFAULT && Peek() != Token::RBRACE){ + //not empty case; + do { + Handle stmt = ParseStatement(); + list->Insert(stmt); + } while (Peek() != Token::CASE && Peek() != Token::DEFAULT && Peek() != Token::RBRACE); + } + + auto block = builder()->NewCaseStatement(clause, list); + block->AsCaseStatement()->set_default(is_default); + return block; +} Handle RAXParser::ParseBreakStatement() { @@ -1008,6 +1122,7 @@ Handle RAXParser::ParseBreakStatement() if (Peek() == Token::IDENTIFIER) { label = builder()->NewIdentifier(GetIdentifierName()); } + EXPECT(Token::SEMICOLON); return builder()->NewBreakStatement(label); } @@ -1069,10 +1184,10 @@ Handle RAXParser::ParseStatement() return ParseBreakStatement(); case Token::CONTINUE: return ParseContinueStatement(); -// case SWITCH: -// return ParseSwitchStatement(); -// case TRY: -// return ParseTryCatchStatement(); + case Token::SWITCH: + return ParseSwitchStatement(); + case Token::TRY: + return ParseTryCatchStatement(); // case THROW: // return ParseThrowStatement(); } @@ -1104,7 +1219,7 @@ Handle RAXParser::ParseClassBody(std::string &clsname) { Handle clsbody = builder()->NewClassBody(); EXPECT(Token::LBRACE); while (true) { - auto one = ParseClassMethodStatement(clsname); + auto one = ParseClassMemberStatement(clsname); clsbody->Insert(one); auto tok = Peek(); if (tok == Token::SEMICOLON) { @@ -1119,8 +1234,14 @@ Handle RAXParser::ParseClassBody(std::string &clsname) { return clsbody; } -Handle RAXParser::ParseClassMethodStatement(std::string &clsname) { +Handle RAXParser::ParseClassMemberStatement(std::string &clsname) { auto tok = Peek(); + bool is_static = false; + if (tok == Token::STATIC) { + is_static = true; + Advance(); + tok = Peek(); + } if (tok != Token::IDENTIFIER) { throw SyntaxError(lex()->CurrentToken(), "expected a method identifier name"); } @@ -1129,9 +1250,16 @@ Handle RAXParser::ParseClassMethodStatement(std::string &clsname) { tok = Peek(); if (tok == Token::ASSIGN) { Advance(); - Handle arrow_function = ParseAssignExpression(); - arrow_function->AsArrowFunctionStatement()->name() = identifier; - return arrow_function; + Handle expr = ParseAssignExpression(); + if (expr->IsArrowFunctionStatement()) { + expr->AsArrowFunctionStatement()->name() = identifier; + return expr; + } + else { + Handle props = builder()->NewClassProperty(identifier, expr); + props->set_is_static(is_static); + return props; + } } else { auto args = ParseParameterList(); @@ -1270,7 +1398,7 @@ Handle RAXParser::ParseProgram() { Handle exprs = builder()->NewExpressionList(); Handle chunk = builder()->NewChunkStatement(exprs); - exprs->Insert(builder()->NewDeclaration(JSX_GLOBAL_VNODE_INDEX, builder()->NewIntegralConstant(1))); + exprs->Insert(builder()->NewDeclaration(JS_GLOBAL_VNODE_INDEX, builder()->NewIntegralConstant(1))); exprs->Insert(builder()->NewDeclaration(JS_GLOBAL_ARGUMENTS, builder()->NewArrayConstant({}))); try { while (Peek() != Token::EOS) { @@ -1278,15 +1406,11 @@ Handle RAXParser::ParseProgram() } } catch (std::exception &e) { auto error = static_cast(&e); - if (error) { - std::cerr << error->what() << " (" << error->token().position().row() - << ":" << error->token().position().col() - << ") (" << error->token().view() << ")" << std::endl; + std::cerr << error->what() << std::endl; } throw; } - return chunk; } @@ -1399,7 +1523,29 @@ Handle RAXParser::ParseVariableStatement() return builder()->factory()->NewDeclarationList(builder()->locator()->location(), scope_manager()->current(), decl_list); } - + +Handle RAXParser::ParseTryCatchStatement() { + Handle try_block = nullptr; + Handle catch_expr = nullptr; + Handle catch_block = nullptr; + Handle finally = nullptr; + EXPECT(Token::TRY); + try_block = ParseBlockStatement(); + if (Peek() == Token::CATCH) { + Advance(); + EXPECT(Token::LPAREN); + catch_expr = ParseExpression(); + EXPECT(Token::RPAREN); + catch_block = ParseBlockStatement(); + } + if (Peek() == Token::FINALLY) { + Advance(); + finally = ParseBlockStatement(); + } + return builder()->NewTryCatchStatement(try_block, catch_expr, catch_block, + finally); +} + Handle ParseProgram(RAXParser *parser) { // parse program and return AST diff --git a/weex_core/Source/core/data_render/rax_parser.h b/weex_core/Source/core/data_render/rax_parser.h index 659fbe12d7..19bd33c2e7 100644 --- a/weex_core/Source/core/data_render/rax_parser.h +++ b/weex_core/Source/core/data_render/rax_parser.h @@ -91,6 +91,9 @@ class RAXParser { Handle ParseIfStatement(); Handle ParseElseBranch(); Handle ParseContinueStatement(); + Handle ParseSwitchStatement(); + Handle ParseTryCatchStatement(); + Handle ParseCaseBlock(bool is_default = false); Handle ParseBreakStatement(); Handle ParseReturnStatement(); Handle ParseForStatement(); @@ -101,7 +104,7 @@ class RAXParser { Handle ParseDeclaration(); Handle ParseClassStatement(); Handle ParseClassBody(std::string &clsname); - Handle ParseClassMethodStatement(std::string &clsname); + Handle ParseClassMemberStatement(std::string &clsname); Handle ParseJSXNodeProperty(); private: const std::string& GetIdentifierName(); @@ -109,7 +112,7 @@ class RAXParser { double ParseNumber(const Token &token); Token::Type Peek(); - void Advance(bool not_regex = true); + void Advance(bool not_regex = false); Tokenizer *lex() { return lex_; } ParserContext *context() { return ctx_; } ScopeManager *scope_manager() { return manager_; } diff --git a/weex_core/Source/core/data_render/statement.h b/weex_core/Source/core/data_render/statement.h index acd7e1ffa6..3628becbf0 100755 --- a/weex_core/Source/core/data_render/statement.h +++ b/weex_core/Source/core/data_render/statement.h @@ -96,7 +96,7 @@ class ContinueStatement : public Expression { private: Handle label_; }; - + // FunctionPrototype - captures the prototype of the function // which includes the name of the function and class FunctionPrototype : public Expression { @@ -118,7 +118,7 @@ class FunctionPrototype : public Expression { std::string name_; std::vector args_; }; - + class MethodStatement : public Expression { DEFINE_NODE_TYPE(MethodStatement, Expression); public: @@ -133,7 +133,7 @@ class MethodStatement : public Expression { Handle function_; bool static_; }; - + // FunctionStatement - captures the function statement class FunctionStatement : public Expression { DEFINE_NODE_TYPE(FunctionStatement, Expression); @@ -153,7 +153,7 @@ class FunctionStatement : public Expression { Handle proto_{nullptr}; Handle body_; }; - + // ArrowFunctionStatement class ArrowFunctionStatement : public Expression { DEFINE_NODE_TYPE(ArrowFunctionStatement, Expression); @@ -196,7 +196,7 @@ class IfElseStatement : public Expression { : Expression(), condition_{ (cond) }, body_{ (body) }, else_{ (el) } { } - + Handle condition() { return condition_; } Handle body() { return body_; } Handle els() { return else_; } @@ -205,16 +205,16 @@ class IfElseStatement : public Expression { Handle body_; Handle else_; }; - + class LabelledStatement : public Expression { public: LabelledStatement(Position &loc, Scope *scope, std::string &label, Handle expr) : Expression(loc, scope), label_{ label }, expr_{ expr } { } - + Handle expr() { return expr_; } std::string &label() { return label_; } - + DEFINE_NODE_TYPE(LabelledStatement, Expression); private: std::string label_; @@ -234,12 +234,45 @@ class ReturnStatement : public Expression { private: Handle expr_; }; - + +class CaseStatement : public Expression { + public: + CaseStatement(Handle text_case, Handle statements) + : Expression(), text_case_{(text_case)}, expr_(statements) { + default_ = false; + } + + Handle test_case() { return text_case_; } + Handle statements() { return expr_; } + void set_default(bool flag) { default_ = flag; } + bool is_default() { return default_; } + + DEFINE_NODE_TYPE(CaseStatement, Expression); + private: + Handle text_case_; + Handle expr_; + bool default_; +}; + +class SwitchStatement : public Expression { + public: + SwitchStatement(Handle test_value,std::vector> cases) + : Expression(), test_value_{ test_value },cases_ { cases}{} + + Handle test_case() { return test_value_; } + const std::vector>& get_cases(){ return cases_;} + + DEFINE_NODE_TYPE(SwitchStatement, Expression); + private: + Handle test_value_; + std::vector> cases_; +}; + class ClassStatement : public Expression { public: ClassStatement(Position &loc, Scope *scope, Handle identifier, Handle super_class, Handle body) : Expression(loc, scope), identifier_{ identifier }, super_class_{super_class}, body_{body} { } - + Handle &Identifier() { return identifier_; } Handle &Body () { return body_; } Handle &Super() { return super_class_; } diff --git a/weex_core/Source/core/data_render/string_table.cc b/weex_core/Source/core/data_render/string_table.cc index d0152f1b67..582a86de19 100644 --- a/weex_core/Source/core/data_render/string_table.cc +++ b/weex_core/Source/core/data_render/string_table.cc @@ -17,6 +17,7 @@ * under the License. */ +#include #include "core/data_render/string_table.h" namespace weex { diff --git a/weex_core/Source/core/data_render/table.cc b/weex_core/Source/core/data_render/table.cc index fc320c44e2..8679e3f95b 100644 --- a/weex_core/Source/core/data_render/table.cc +++ b/weex_core/Source/core/data_render/table.cc @@ -16,6 +16,8 @@ * specific language governing permissions and limitations * under the License. */ + +#include #include #include "core/data_render/object.h" #include "core/data_render/table.h" @@ -26,15 +28,6 @@ namespace weex { namespace core { namespace data_render { -int IndexOf(const std::vector *arr, const Value *val) { - auto it = std::find(arr->begin(), arr->end(), val); - if (it != arr->end()) { - return static_cast(std::distance(arr->begin(), it)); - } else { - return -1; - } -} - int SetTableForTable(Table *table, const Value *src) { int ret = 0; do { @@ -227,6 +220,9 @@ json11::Json TableToJson(Table *table) { if (it->second.type == Value::FUNC) { object.insert({it->first, json11::Json("FUNC")}); } + if (it->second.type == Value::FUNC_INST) { + object.insert({it->first, json11::Json("FUNC_INST")}); + } } return json11::Json(object); } diff --git a/weex_core/Source/core/data_render/token.h b/weex_core/Source/core/data_render/token.h index dddd9602d4..c67296b470 100644 --- a/weex_core/Source/core/data_render/token.h +++ b/weex_core/Source/core/data_render/token.h @@ -94,7 +94,11 @@ namespace data_render { T(GT, ">", 10) \ T(LTE, "<=", 10) \ T(GTE, ">=", 10) \ - T(ARROW_FUNCTION, "=>", 10) \ + T(ARROW_FUNCTION, "=>", 10) \ + \ + /*jsx */ \ + T(JSX_TAG_CLOSE,"",0) \ \ /* Unary operators. */ \ /* IsUnaryOp() relies on this block of enum values */ \ @@ -105,6 +109,8 @@ namespace data_render { \ /* Keywords (ECMA-262, section 7.5.2, page 13). */ \ K(BREAK, "break", 0) \ + K(CASE, "case", 0) \ + K(DEFAULT, "default", 0) \ K(CONTINUE, "continue", 0) \ K(ELSE, "else", 0) \ K(FOR, "for", 0) \ @@ -112,6 +118,9 @@ namespace data_render { K(IF, "if", 0) \ K(RETURN, "return", 0) \ K(SWITCH, "switch", 0) \ + K(TRY, "try", 0) \ + K(CATCH, "catch", 0) \ + K(FINALLY, "finally", 0) \ K(VAR, "var", 0) \ \ /* Literals (ECMA-262, section 7.8, page 16). */ \ @@ -129,6 +138,7 @@ namespace data_render { K(EXTENDS, "extends", 0) \ K(SUPER, "super", 0) \ K(LET, "let", 0) \ + K(STATIC, "static", 0) \ \ T(EOS, "EOS", 0) \ T(INTEGER, "INTEGER", 0) \ diff --git a/weex_core/Source/core/data_render/tokenizer.cc b/weex_core/Source/core/data_render/tokenizer.cc index a229196032..ddf9070abd 100644 --- a/weex_core/Source/core/data_render/tokenizer.cc +++ b/weex_core/Source/core/data_render/tokenizer.cc @@ -267,6 +267,9 @@ Token::Type IsTwoCharacterSymbol(char ch1, char ch2) { case '>': if (ch1 == '>') return Token::SAR; + case '/': + if (ch1 == '<') + return Token::JSX_TAG_CLOSE; default: return Token::INVALID; } @@ -366,6 +369,8 @@ Token Tokenizer::AdvanceInternal(bool not_regex) { return Token(std::string("ERROR"), Token::ERROR, _ position(), _ seek()); } + } else if(next == '>'){ + return Token("/>",Token::JSX_TAG_END,_ position(), _ seek()); } else { bool ok = true; _ PutBack(next); @@ -514,9 +519,6 @@ Token Tokenizer::ParseRegex(bool* ok) { buffer.push_back(ch); ch = _ ReadChar(); } - - if (ch == ']') - buffer.push_back(ch); } if (ch == '\\') { diff --git a/weex_core/Source/core/data_render/vm.cc b/weex_core/Source/core/data_render/vm.cc index 036cebbd0d..000fa4d8f3 100644 --- a/weex_core/Source/core/data_render/vm.cc +++ b/weex_core/Source/core/data_render/vm.cc @@ -24,6 +24,7 @@ #include "core/data_render/common_error.h" #include "core/data_render/class_array.h" #include "core/data_render/monitor/vm_monitor.h" +#include "core/data_render/class_function.h" namespace weex { namespace core { @@ -44,16 +45,16 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { while (pc != frame.end) { Instruction instruction = *pc++; double d1, d2; - OpCode op(GET_OP_CODE(instruction)); + OPCode op(GET_OP_CODE(instruction)); #if DEBUG //tc.op_start(op); #endif switch (op) { case OP_MOVE: { - LOGTEMP("OP_MOVE A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_B(instruction)); + LOGTEMP("OP_MOVE A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_Bx(instruction)); a = frame.reg + GET_ARG_A(instruction); - b = frame.reg + GET_ARG_B(instruction); + b = frame.reg + GET_ARG_Bx(instruction); if (IsValueRef(a)) { *a->var = *b; SetNil(a); @@ -67,13 +68,13 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { break; } case OP_LOADNULL: - a = frame.reg + GET_ARG_A(instruction); + a = frame.reg + GET_ARG_Ax(instruction); a->type = Value::Type::NIL; break; case OP_LOADK: LOGTEMP("OP_LOADK A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_Bx(instruction)); a = frame.reg + GET_ARG_A(instruction); - b = frame.func->f->GetConstant((int)GET_ARG_Bx(instruction)); + b = frame.func->GetConstant((int)GET_ARG_Bx(instruction)); *a = *b; break; case OP_GETGLOBAL: @@ -85,8 +86,15 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { case OP_GETFUNC: { LOGTEMP("OP_GETFUNC A:%ld\n", GET_ARG_A(instruction)); a = frame.reg + GET_ARG_A(instruction); - a->type = Value::Type::FUNC; - a->f = frame.func->f->GetChild(GET_ARG_Bx(instruction)); + FuncState *func_state = frame.func->GetChild(GET_ARG_Bx(instruction)); + if (func_state->in_closure().size() > 0) { + *a = exec_state->class_factory()->CreateFuncInstance(func_state); + AddClosure(exec_state, a); + } + else { + a->type = Value::Type::FUNC; + a->f = func_state; + } break; } @@ -236,7 +244,42 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { } break; } - + case OP_TRUE_JMP: { + LOGTEMP("OP_TRUE_JMP A:%ld B:%ld \n", GET_ARG_A(instruction), GET_ARG_Bx(instruction)); + a = frame.reg + GET_ARG_A(instruction); + bool con = false; + if (!ToBool(a, con)) { + throw VMExecError("Unspport Type With OP_CODE [OP_JMP]"); + } + if (con) { + pc += GET_ARG_Bx(instruction); + } + break; + } + case OP_JMPTO: { + LOGTEMP("OP_JMPTO A:%ld B:%ld \n", GET_ARG_A(instruction), GET_ARG_Bx(instruction)); + a = frame.reg + GET_ARG_A(instruction); + bool con = false; + if (!ToBool(a, con)) { + throw VMExecError("Unspport Type With OP_CODE [OP_JMP]"); + } + if (!con) { + pc = frame.pc + GET_ARG_Bx(instruction); + } + break; + } + case OP_TRUE_JMPTO: { + LOGTEMP("OP_TRUE_JMPTO A:%ld B:%ld \n", GET_ARG_A(instruction), GET_ARG_Bx(instruction)); + a = frame.reg + GET_ARG_A(instruction); + bool con = false; + if (!ToBool(a, con)) { + throw VMExecError("Unspport Type With OP_CODE [OP_JMP]"); + } + if (con) { + pc = frame.pc + GET_ARG_Bx(instruction); + } + break; + } case OP_GOTO: { pc = frame.pc + GET_ARG_Ax(instruction); } @@ -298,9 +341,9 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { } case OP_NOT: { - LOGTEMP("OP_NOT A:%ld B:%ld \n", GET_ARG_A(instruction), GET_ARG_B(instruction)); + LOGTEMP("OP_NOT A:%ld B:%ld \n", GET_ARG_A(instruction), GET_ARG_Bx(instruction)); a = frame.reg + GET_ARG_A(instruction); - b = frame.reg + GET_ARG_B(instruction); + b = frame.reg + GET_ARG_Bx(instruction); a->type = Value::Type::BOOL; ToBool(b, a->b); a->b = !a->b; @@ -406,7 +449,7 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { break; case OP_POST_INCR: { a = frame.reg + GET_ARG_A(instruction); - b = frame.reg + GET_ARG_B(instruction); + b = frame.reg + GET_ARG_Bx(instruction); if (IsInt(a)) { if (NULL != b) { SetIValue(b, (int)IntValue(a)); @@ -429,15 +472,15 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { case OP_POST_DECR: { a = frame.reg + GET_ARG_A(instruction); - b = frame.reg + GET_ARG_B(instruction); + b = frame.reg + GET_ARG_Bx(instruction); if (IsInt(a)) { - if (GET_ARG_B(instruction) != 0) { + if (GET_ARG_Bx(instruction) != 0) { SetIValue(b, (int)IntValue(a)); } SetIValue(a, (int)IntValue(a) - 1); } else if (IsNumber(a)) { - if (GET_ARG_B(instruction) != 0) { + if (GET_ARG_Bx(instruction) != 0) { SetDValue(b, NumValue(a)); } SetDValue(a, NumValue(a) - 1); @@ -448,9 +491,9 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { } break; - case OP_PRE_INCR: { + case OP_PREV_INCR: { a = frame.reg + GET_ARG_A(instruction); - b = frame.reg + GET_ARG_B(instruction); + b = frame.reg + GET_ARG_Bx(instruction); if (IsInt(a)) { SetIValue(a, (int)IntValue(a) + 1); SetRefValue(a); @@ -469,17 +512,17 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { } break; - case OP_PRE_DECR: { + case OP_PREV_DECR: { a = frame.reg + GET_ARG_A(instruction); - b = frame.reg + GET_ARG_B(instruction); + b = frame.reg + GET_ARG_Bx(instruction); if (IsInt(a)) { SetIValue(a, static_cast(IntValue(a)) - 1); - if (GET_ARG_B(instruction) != 0) { + if (GET_ARG_Bx(instruction) != 0) { SetIValue(b, static_cast(IntValue(a))); } } else if (IsNumber(a)) { SetDValue(a, NumValue(a) - 1); - if (GET_ARG_B(instruction) != 0) { + if (GET_ARG_Bx(instruction) != 0) { SetDValue(b, NumValue(a)); } } else { @@ -517,6 +560,24 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { } break; } + case OP_CONSTRUCTOR: + { + a = frame.reg + GET_ARG_A(instruction); + int argc = (int)GET_ARG_B(instruction); + c = frame.reg + GET_ARG_C(instruction); + if (!IsClassInstance(a)) { + throw VMExecError("only support class instance in [OP_CONSTRUCTOR]"); + break; + } + if (argc < 1) { + throw VMExecError("constructor with no args in [OP_CONSTRUCTOR]"); + break; + } + if (FindConstructor(ValueTo(a), c, c + 1)) { + exec_state->CallFunction(c, argc, a); + } + break; + } case OP_GETSUPER: { LOGTEMP("OP_GETSUPER A:%ld B:%ld C:%ld\n", GET_ARG_A(instruction), GET_ARG_B(instruction), GET_ARG_C(instruction)); @@ -531,19 +592,21 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { if (!inst_super) { throw VMExecError("Instance Can't Find Super With OP_CODE [OP_GETSUPER]"); } + SetCIValue(a, reinterpret_cast(inst->p_super_)); int index = inst_super->p_desc_->funcs_->IndexOf("constructor"); - if (index < 0) { - throw VMExecError("Can't Find Super Constructor With OP_CODE [OP_GETSUPER]"); + if (index >= 0) { + *c = *inst_super->p_desc_->funcs_->Find(index); + } + else { + SetNil(c); } - SetCIValue(a, reinterpret_cast(inst->p_super_)); - *c = *inst_super->p_desc_->funcs_->Find(index); break; } case OP_SETMEMBERVAR: { - LOGTEMP("OP_SETMEMBERVAR A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_B(instruction)); + LOGTEMP("OP_SETMEMBERVAR A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_Bx(instruction)); a = frame.reg + GET_ARG_A(instruction); - b = frame.reg + GET_ARG_B(instruction); + b = frame.reg + GET_ARG_Bx(instruction); if (!IsValueRef(a)) { throw VMExecError("Only ValueRef Support With OP_CODE [OP_SETMEMBER]"); } @@ -628,23 +691,18 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { } } else if (IsString(b)) { - if (var_name == "length") { - //*a = GetStringLength(ValueTo(b)); + int index = exec_state->global()->IndexOf("String"); + if (index < 0) { + throw VMExecError("Can't Find String Class With OP_CODE OP_GETMEMBER"); } - else { - int index = exec_state->global()->IndexOf("String"); - if (index < 0) { - throw VMExecError("Can't Find String Class With OP_CODE OP_GETMEMBER"); - } - Value *class_desc = exec_state->global()->Find(index); - Variables *funcs = ValueTo(class_desc)->funcs_.get(); - index = funcs->IndexOf(var_name); - if (index < 0) { - throw VMExecError("Can't Find String Func " + var_name + " With OP_CODE [OP_GETMEMBER]"); - } - Value *func = funcs->Find(index); - *a = *func; + Value *class_desc = exec_state->global()->Find(index); + Variables *funcs = ValueTo(class_desc)->funcs_.get(); + index = funcs->IndexOf(var_name); + if (index < 0) { + throw VMExecError("Can't Find String Func " + var_name + " With OP_CODE [OP_GETMEMBER]"); } + Value *func = funcs->Find(index); + *a = *func; } else if (IsTable(b)) { if (op == OP_GETMEMBER) { @@ -665,33 +723,64 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { } else { // only can find class static funcs; - Variables *funcs = ValueTo(b)->static_funcs_.get(); - int index = funcs->IndexOf(var_name); + Variables *statics = ValueTo(b)->statics_.get(); + int index = statics->IndexOf(var_name); if (index < 0) { - throw VMExecError("Can't Find Static Func " + var_name + " With OP_CODE [OP_GETMEMBER]"); + if (op == OP_GETMEMBER) { + throw VMExecError("Can't Find Static Func " + var_name + " With OP_CODE [OP_GETMEMBER]"); + break; + } + Value *ret = GetClassStaticMemberVar(ValueTo(b), var_name); + SetValueRef(a, ret); + } + else { + Value *svar = statics->Find(index); + *a = *svar; } - Value *func = funcs->Find(index); - *a = *func; } break; } case OP_SETOUTVAR: { - LOGTEMP("OP_SETOUTVAR A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_B(instruction)); + LOGTEMP("OP_SETOUTVAR A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_Bx(instruction)); a = frame.reg + GET_ARG_A(instruction); int index = (int)GET_ARG_Bx(instruction); ValueRef *ref = exec_state->FindRef(index); if (!ref) { - throw VMExecError("Can't Find ValueRef " + to_string(index) + " [OP_SETOUTVAR]"); + throw VMExecError("Can't Find ValueRef " + base::to_string(index) + " [OP_SETOUTVAR]"); } ref->value() = *a; ref->value().ref = a; break; } - case OP_RESETOUTVAR: + case OP_TYPEOF: { - LOGTEMP("OP_RESETOUTVAR A:%ld\n", GET_ARG_A(instruction)); a = frame.reg + GET_ARG_A(instruction); + b = frame.reg + GET_ARG_Bx(instruction); + if (IsNil(b)) { + SetSValue(a, exec_state->string_table()->StringFromUTF8("undefined")); + } + else if (IsTable(b)) { + SetSValue(a, exec_state->string_table()->StringFromUTF8("object")); + } + else if (IsBool(b)) { + SetSValue(a, exec_state->string_table()->StringFromUTF8("boolean")); + } + else if (IsString(b)) { + SetSValue(a, exec_state->string_table()->StringFromUTF8("string")); + } + else if (IsFunction(b) || IsFuncInstance(b)) { + SetSValue(a, exec_state->string_table()->StringFromUTF8("function")); + } + else { + throw VMExecError("Can't Supporting typeof [OP_TYPEOF]"); + } + break; + } + case OP_RESETOUTVAR: + { + LOGTEMP("OP_RESETOUTVAR A:%ld\n", GET_ARG_Ax(instruction)); + a = frame.reg + GET_ARG_Ax(instruction); a->ref = NULL; break; } @@ -702,12 +791,57 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { int index = (int)GET_ARG_Bx(instruction); ValueRef *ref = exec_state->FindRef(index); if (!ref) { - throw VMExecError("Can't Find ValueRef " + to_string(index) + " [OP_GETOUTVAR]"); + throw VMExecError("Can't Find ValueRef " + base::to_string(index) + " [OP_GETOUTVAR]"); } *a = ref->value(); a->ref = &ref->value(); break; } + case OP_OUT_CLOSURE: + { + LOGTEMP("OP_OUT_CLOSURE A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_Bx(instruction)); + a = frame.reg + GET_ARG_A(instruction); + int index = (int)GET_ARG_Bx(instruction); + ValueRef *ref = exec_state->FindRef(index); + if (!ref) { + throw VMExecError("Can't Find ValueRef " + base::to_string(index) + " [OP_OUT_CLOSURE]"); + } + ref->value() = *a; + ref->value().ref = a; + if (ref->is_closure() && ref->closure()) { + ref->closure()->value() = *a; + } + break; + } + case OP_IN_CLOSURE: + { + LOGTEMP("OP_IN_CLOSURE A:%ld B:%ld\n", GET_ARG_A(instruction), GET_ARG_Bx(instruction)); + a = frame.reg + GET_ARG_A(instruction); + int index = (int)GET_ARG_Bx(instruction); + ValueRef *ref = exec_state->FindRef(index); + if (!ref) { + throw VMExecError("Can't Find ValueRef " + base::to_string(index) + " [OP_IN_CLOSURE]"); + } + Value *ret = LoadClosure(frame.reg, ref); + if (!ret) { + throw VMExecError("Can't Find Closure [OP_IN_CLOSURE]"); + } + *a = *ret; + a->ref = ret; + break; + } + case OP_REMOVE_CLOSURE: + { + LOGTEMP("OP_REMOVE_CLOSURE A:%ld \n", GET_ARG_Ax(instruction)); + int index = (int)GET_ARG_Ax(instruction); + ValueRef *ref = exec_state->FindRef(index); + if (!ref) { + throw VMExecError("Can't Find ValueRef " + base::to_string(index) + " [OP_REMOVE_CLOSURE]"); + } + ref->value().ref = nullptr; + ref->closure()->SetValueRef(nullptr); + break; + } case OP_GETINDEXVAR: { LOGTEMP("OP_GETINDEXVAR A:%ld B:%ld C:%ld\n", GET_ARG_A(instruction), GET_ARG_B(instruction), GET_ARG_C(instruction)); @@ -817,12 +951,12 @@ void VM::RunFrame(ExecState *exec_state, Frame frame, Value *ret) { return; } case OP_RETURN1: { - LOGTEMP("OP_RETURN1 A:%ld\n", GET_ARG_A(instruction)); + LOGTEMP("OP_RETURN1 A:%ld\n", GET_ARG_Ax(instruction)); if (ret == nullptr) { return; } else { - a = frame.reg + GET_ARG_A(instruction); + a = frame.reg + GET_ARG_Ax(instruction); *ret = *a; return; } diff --git a/weex_core/Source/core/data_render/vm.h b/weex_core/Source/core/data_render/vm.h index 287c6cab87..fecb19f452 100644 --- a/weex_core/Source/core/data_render/vm.h +++ b/weex_core/Source/core/data_render/vm.h @@ -36,7 +36,7 @@ class Value; struct Frame { Value *reg; Value *ret; - Value *func; + FuncState *func; const Instruction *pc; const Instruction *end; }; diff --git a/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc b/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc index 6dab8b0e1a..68a5a3d9a2 100644 --- a/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc +++ b/weex_core/Source/core/data_render/vnode/vnode_exec_env.cc @@ -17,8 +17,8 @@ * under the License. */ -#include "core/data_render/vnode/vnode_exec_env.h" #include +#include "core/data_render/vnode/vnode_exec_env.h" #include "core/data_render/object.h" #include "core/data_render/table.h" #include "core/data_render/class_factory.h" @@ -37,41 +37,6 @@ namespace data_render { json11::Json ValueToJSON(const Value& value); -static Value Log(ExecState *exec_state) { - size_t length = exec_state->GetArgumentCount(); - std::stringstream ss; - for (int i = 0; i < length; ++i) { - Value *a = exec_state->GetArgument(i); - switch (a->type) { - case Value::Type::NUMBER: - ss << "[log]:=>" << a->n << "\n"; - break; - case Value::Type::INT: - ss << "[log]:=>" << a->i << "\n"; - break; - case Value::Type::STRING: - ss << "[log]:=>" << a->str->c_str() << "\n"; - break; - case Value::Type::TABLE: - ss << "[log]:=>" << TableToString(ValueTo
(a)) << "\n"; - break; - case Value::Type::ARRAY: - ss << "[log]:=>" << ArrayToString(ValueTo(a)) << "\n"; - break; - case Value::Type::CPTR: - { - VNode *node = (VNode *)a->cptr; - ss << "[log]:=> cptr" << node->tag_name() <<"\n"; - break; - } - default: - break; - } - } - LOGD("%s",ss.str().c_str()); - return Value(); -} - static Value SizeOf(ExecState *exec_state) { size_t length = exec_state->GetArgumentCount(); if (length > 0) { @@ -179,6 +144,27 @@ static Value CallNativeModule(ExecState *exec_state) { return Value(); } +static Value RequireModule(ExecState *exec_state) { + do { + if (!exec_state->GetArgumentCount()) { + break; + } + Value *arg = exec_state->GetArgument(0); + if (!IsString(arg)) { + break; + } + std::string module_name = CStringValue(arg); + std::string module_info; + if (!weex::core::data_render::VNodeRenderManager::GetInstance()->RequireModule(exec_state, module_name, module_info)) { + break; + } + return StringToValue(exec_state, module_info); + + } while (0); + + return Value(); +} + static Value RegisterModules(ExecState *exec_state) { do { if (!exec_state->GetArgumentCount()) { @@ -467,12 +453,12 @@ static Value SetProps(ExecState *exec_state) { } case Value::INT: { - node->SetStyle(iter_style->first, to_string(iter_style->second.i)); + node->SetStyle(iter_style->first, base::to_string(iter_style->second.i)); break; } case Value::NUMBER: { - node->SetStyle(iter_style->first, to_string(iter_style->second.n)); + node->SetStyle(iter_style->first, base::to_string(iter_style->second.n)); break; } default: @@ -491,7 +477,7 @@ static Value SetProps(ExecState *exec_state) { } case Value::INT: { - node->SetAttribute(iter->first, to_string(iter->second.i)); + node->SetAttribute(iter->first, base::to_string(iter->second.i)); break; } case Value::FUNC: @@ -506,16 +492,28 @@ static Value SetProps(ExecState *exec_state) { node->AddEvent(event, func_state, func_state->class_inst()); break; } + case Value::FUNC_INST: + { + std::string::size_type pos = iter->first.find("on"); + if (pos != 0) { + throw VMExecError("AddEvent isn't a function"); + } + std::string event = iter->first.substr(pos + 2); + transform(event.begin(), event.end(), event.begin(), ::tolower); + FuncInstance *func_inst = ValueTo(&iter->second); + FuncState *func_state = func_inst->func_; + node->AddEvent(event, func_inst, func_state->class_inst()); + break; + } case Value::NUMBER: { - node->SetStyle(iter->first, to_string(iter->second.n)); + node->SetStyle(iter->first, base::to_string(iter->second.n)); break; } default: LOGE("can't support type:%i\n", iter->second.type); break; } - } } } @@ -559,8 +557,7 @@ static Value SetStyle(ExecState* exec_state) { return Value(); } -void VNodeExecEnv::InitCFuncEnv(ExecState *state) { - state->Register("log", Log); +void VNodeExecEnv::ImportExecEnv(ExecState *state) { state->Register("sizeof", SizeOf); state->Register("slice", Slice); state->Register("appendUrlParam", AppendUrlParam); @@ -573,16 +570,24 @@ void VNodeExecEnv::InitCFuncEnv(ExecState *state) { state->Register("appendChildComponent", AppendChildComponent); state->Register("appendChild", AppendChild); state->Register("encodeURIComponent", encodeURIComponent); + state->Register("encodeURI", encodeURIComponent); state->Register("setAttr", SetAttr); state->Register("setProps", SetProps); state->Register("setClassList", SetClassList); state->Register("setStyle", SetStyle); state->Register("__callNativeModule", CallNativeModule); + // __registerModules deprecated in sversion 5.8 + state->Register("__registerModules", RegisterModules); + // __requireModule supporting in sversion 5.8 + + state->Register("__requireModule", RequireModule); state->Register("Array", state->class_factory()->ClassArray()); state->Register("String", state->class_factory()->ClassString()); state->Register("JSON", state->class_factory()->ClassJSON()); state->Register("Object", state->class_factory()->ClassObject()); + state->Register("RegExp", state->class_factory()->ClassRegExp()); + state->Register("window", state->class_factory()->ClassWindow()); + state->Register("Math", state->class_factory()->ClassMath()); + state->Register("console", state->class_factory()->ClassConsole()); RegisterJSCommonFunction(state); } @@ -656,7 +661,7 @@ json11::Json ValueToJSON(const Value& value) { return json11::Json(object); } -void VNodeExecEnv::InitGlobalValue(ExecState* state) { +void VNodeExecEnv::ParseData(ExecState* state) { const json11::Json& json = state->context()->raw_json(); Variables* global = state->global(); const json11::Json& data = json["data"]; @@ -688,7 +693,7 @@ void VNodeExecEnv::InitGlobalValue(ExecState* state) { global->Add("_components_props", components_props); } -void VNodeExecEnv::InitInitDataValue(ExecState *state, const std::string& init_data_str) { +void VNodeExecEnv::ImportExecData(ExecState *state, const std::string& init_data_str) { std::string err; const json11::Json& json = json11::Json::parse(init_data_str, err); if (!err.empty()) { @@ -715,7 +720,7 @@ void AddStyles(ExecState* state, const std::string& prefix, const json11::Json& } } -void VNodeExecEnv::InitStyleList(ExecState* state) { +void VNodeExecEnv::ParseStyle(ExecState *state) { json11::Json& json = state->context()->raw_json(); //body styles @@ -742,7 +747,6 @@ Value StringToValue(ExecState *exec_state,const std::string &str) { std::string err; json11::Json json = json11::Json::parse(str, err); if (!err.empty() || json.is_null()) { - ret = exec_state->string_table()->StringFromUTF8(str); break; } ret = JSONToValue(exec_state, json); diff --git a/weex_core/Source/core/data_render/vnode/vnode_exec_env.h b/weex_core/Source/core/data_render/vnode/vnode_exec_env.h index 87ebc90871..aad432ece9 100644 --- a/weex_core/Source/core/data_render/vnode/vnode_exec_env.h +++ b/weex_core/Source/core/data_render/vnode/vnode_exec_env.h @@ -28,11 +28,10 @@ namespace data_render { class VNodeExecEnv { public: - static void InitCFuncEnv(ExecState* state); - static void InitGlobalValue(ExecState* state); - static void InitInitDataValue(ExecState* state, - const std::string& init_data_str); - static void InitStyleList(ExecState* state); + static void ImportExecEnv(ExecState *state); + static void ImportExecData(ExecState *state, const std::string &init_data_str); + static void ParseStyle(ExecState *state); + static void ParseData(ExecState *state); }; Value StringToValue(ExecState *exec_state, const std::string &str); diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_context.h b/weex_core/Source/core/data_render/vnode/vnode_render_context.h index b585783e1e..45769fbe88 100644 --- a/weex_core/Source/core/data_render/vnode/vnode_render_context.h +++ b/weex_core/Source/core/data_render/vnode/vnode_render_context.h @@ -50,7 +50,7 @@ class VNodeRenderContext { private: // node context std::string page_id_; - VNode* root_; + VNode *root_; json11::Json raw_json_; std::string raw_source_; // script to execute diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc b/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc index cdff7efd3c..708138b713 100644 --- a/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc +++ b/weex_core/Source/core/data_render/vnode/vnode_render_manager.cc @@ -17,10 +17,11 @@ * under the License. */ -#include "core/data_render/vnode/vnode_render_manager.h" #include #include -#include "base/string_util.h" +#include "core/data_render/vnode/vnode_render_manager.h" +#include "core/data_render/common_error.h" +#include "core/data_render/exec_state_binary.h" #include "core/data_render/exec_state.h" #include "core/data_render/string_table.h" #include "core/data_render/vnode/vnode.h" @@ -29,8 +30,6 @@ #include "core/render/manager/render_manager.h" #include "core/render/node/factory/render_creator.h" #include "core/bridge/platform_bridge.h" -#include "core/data_render/binary_file.h" -#include "core/data_render/common_error.h" #define VRENDER_LOG true @@ -167,18 +166,18 @@ void VNodeRenderManager::InitVM() { } void VNodeRenderManager::CreatePage(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data) { - std::string err = CreatePageImpl(input, page_id, options, init_data); + std::string err = CreatePageWithContent(input, page_id, options, init_data); if (!err.empty()) { WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(page_id.c_str(), nullptr, err.c_str()); } } -std::string VNodeRenderManager::CreatePageImpl(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data) { +std::string VNodeRenderManager::CreatePageWithContent(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data) { InitVM(); auto start = std::chrono::steady_clock::now(); ExecState *exec_state = new ExecState(g_vm); exec_states_.insert({page_id, exec_state}); - VNodeExecEnv::InitCFuncEnv(exec_state); + VNodeExecEnv::ImportExecEnv(exec_state); std::string err; json11::Json json = json11::Json::parse(input, err); if (!err.empty() || json.is_null()) { @@ -186,12 +185,12 @@ std::string VNodeRenderManager::CreatePageImpl(const std::string &input, const s } else { exec_state->context()->raw_json() = json; + VNodeExecEnv::ParseData(exec_state); + VNodeExecEnv::ParseStyle(exec_state); } - VNodeExecEnv::InitGlobalValue(exec_state); if (init_data.length() > 0) { - VNodeExecEnv::InitInitDataValue(exec_state, init_data); + VNodeExecEnv::ImportExecData(exec_state, init_data); } - VNodeExecEnv::InitStyleList(exec_state); exec_state->context()->page_id(page_id); //auto compile_start = std::chrono::steady_clock::now(); exec_state->Compile(err); @@ -217,6 +216,26 @@ std::string VNodeRenderManager::CreatePageImpl(const std::string &input, const s return err; } +bool VNodeRenderManager::RequireModule(ExecState *exec_state, std::string &name, std::string &result) +{ + bool finished = false; + do { + if (!modules_.size()) { + break; + } + for (auto iter = modules_.begin(); iter != modules_.end(); iter++) { + if ((*iter).find(name) <= 10) { + result = *iter; + finished = true; + break; + } + } + + } while (0); + + return finished; +} + void VNodeRenderManager::ExecuteRegisterModules(ExecState *exec_state, std::vector& registers) { do { if (!modules_.size()) { @@ -237,26 +256,19 @@ void VNodeRenderManager::ExecuteRegisterModules(ExecState *exec_state, std::vect } while (0); } -std::string VNodeRenderManager::CreatePageWithOpcode(const std::string& page_id, const std::string& options, const std::string& init_data) { +std::string VNodeRenderManager::CreatePageWithContent(const uint8_t *contents, size_t length, const std::string &page_id, const std::string &options, const std::string &init_data) { InitVM(); auto start = std::chrono::steady_clock::now(); ExecState *exec_state = new ExecState(g_vm); exec_states_.insert({page_id, exec_state}); - VNodeExecEnv::InitCFuncEnv(exec_state); + VNodeExecEnv::ImportExecEnv(exec_state); + exec_state->context()->page_id(page_id); std::string err; - try { - exec_state->startDecode(); - } catch (std::exception &e) { - auto error = static_cast(&e); - if (error) { - err = error->what(); - std::cerr << error->what() << std::endl; - } + if (!weex::core::data_render::WXExecDecoder(exec_state, (uint8_t *)contents, length, err)) { return err; } - exec_state->endDecode(); if (init_data.length() > 0) { - VNodeExecEnv::InitInitDataValue(exec_state, init_data); + VNodeExecEnv::ImportExecData(exec_state, init_data); } auto decoder_post = std::chrono::duration_cast(std::chrono::steady_clock::now() - start); LOGD("[DATA_RENDER], Decoder time:[%lld]\n", decoder_post.count()); @@ -274,11 +286,8 @@ std::string VNodeRenderManager::CreatePageWithOpcode(const std::string& page_id, return err; } -void VNodeRenderManager::CreatePage(const char *contents, unsigned long length, const std::string& page_id, const std::string& options, const std::string& init_data) { - BinaryFile *file = BinaryFile::instance(); - file->set_input(contents); - file->set_length(length); - string err = CreatePageWithOpcode(page_id, options, init_data); +void VNodeRenderManager::CreatePage(const char *contents, size_t length, const std::string& page_id, const std::string& options, const std::string& init_data) { + string err = CreatePageWithContent((const uint8_t *)contents, length, page_id, options, init_data); if (!err.empty()) { WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(page_id.c_str(), nullptr, err.c_str()); } @@ -292,7 +301,7 @@ bool VNodeRenderManager::RefreshPage(const std::string& page_id, break; } ExecState *exec_state = it->second; - VNodeExecEnv::InitInitDataValue(exec_state, init_data); + VNodeExecEnv::ImportExecData(exec_state, init_data); std::string err; exec_state->context()->Reset(); exec_state->Execute(err); // refresh root @@ -344,24 +353,48 @@ void VNodeRenderManager::FireEvent(const std::string &page_id, const std::string if (iter_event == vnode->events()->end()) { break; } - FuncState *func_state = (FuncState *)iter_event->second; - if (!func_state) { + if (!iter_event->second) { break; } + FuncState *func_state = nullptr; + FuncInstance *func_inst = nullptr; ExecState *exec_state = iter->second; + bool finder = false; + for (auto iter : exec_state->class_factory()->stores()) { + if (iter.first == iter_event->second) { + if (iter.second == Value::Type::FUNC_INST) { + func_inst = reinterpret_cast(iter.first); + } + finder = true; + } + } + if (!finder) { + func_state = reinterpret_cast(iter_event->second); + } + if (!func_state && !func_inst) { + break; + } std::vector caller_args; + if (func_inst) { + func_state = func_inst->func_; + } if (func_state->is_class_func() && vnode->inst()) { Value inst; SetCIValue(&inst, reinterpret_cast(vnode->inst())); caller_args.push_back(inst); } caller_args.push_back(StringToValue(exec_state, args)); - exec_state->Call(func_state, caller_args); + if (func_inst) { + exec_state->Call(func_inst, caller_args); + } + else { + exec_state->Call(func_state, caller_args); + } } while (0); } -void VNodeRenderManager::CallNativeModule(ExecState* exec_state, +void VNodeRenderManager::CallNativeModule(ExecState *exec_state, const std::string& module, const std::string& method, const std::string& args, int argc) { @@ -378,6 +411,18 @@ void VNodeRenderManager::CallNativeModule(ExecState* exec_state, } } } + +void VNodeRenderManager::WXLogNative(ExecState *exec_state, const std::string &info) { + for (auto iter = exec_states_.begin(); iter != exec_states_.end(); iter++) { + if (iter->second == exec_state) { + WeexCoreManager::Instance() + ->getPlatformBridge() + ->platform_side() + ->NativeLog(info.c_str()); + break; + } + } +} void VNodeRenderManager::PatchVNode(ExecState *exec_state, VNode *v_node, VNode *new_node) { do { @@ -632,10 +677,9 @@ void AddNodes(const string& pageId, vector& vec, for (int i = start; i <= end; ++i) { auto p_node = vec[i]; ref_list.insert(ref_list.begin() + i, p_node); - - WeexCore::RenderObject* root = VNode2RenderObject(p_node, pageId); + WeexCore::RenderObject *node = ParseVNode2RenderObject(p_node, nullptr, false, 0, pageId); RenderManager::GetInstance()->AddRenderObject( - pageId, p_node->parent()->render_object_ref(), i, root); + pageId, p_node->parent()->render_object_ref(), i, node); } } diff --git a/weex_core/Source/core/data_render/vnode/vnode_render_manager.h b/weex_core/Source/core/data_render/vnode/vnode_render_manager.h index 351b172926..85cb3b8b7c 100644 --- a/weex_core/Source/core/data_render/vnode/vnode_render_manager.h +++ b/weex_core/Source/core/data_render/vnode/vnode_render_manager.h @@ -44,15 +44,17 @@ class VNodeRenderManager { public: void CreatePage(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data); - void CreatePage(const char* contents, unsigned long length, const std::string& page_id, const std::string& options, const std::string& init_data); + void CreatePage(const char *contents, size_t length, const std::string& page_id, const std::string& options, const std::string& init_data); bool RefreshPage(const std::string &page_id, const std::string &init_data); bool ClosePage(const std::string &page_id); void FireEvent(const std::string &page_id, const std::string &ref, const std::string &event,const std::string &args); void ExecuteRegisterModules(ExecState *exec_state, std::vector& registers); void RegisterModules(const std::string &modules) { modules_.push_back(modules); } + bool RequireModule(ExecState *exec_state, std::string &name, std::string &result); void PatchVNode(ExecState *exec_state, VNode *v_node, VNode *new_node); void CallNativeModule(ExecState *exec_state, const std::string &module, const std::string &method, const std::string &args, int argc = 0); + void WXLogNative(ExecState *exec_state, const std::string &info); static VNodeRenderManager *GetInstance() { if (!g_instance) { g_instance = new VNodeRenderManager(); @@ -65,8 +67,9 @@ class VNodeRenderManager { bool CreatePageInternal(const std::string &page_id, VNode *v_node); bool RefreshPageInternal(const std::string &page_id, VNode *new_node); bool ClosePageInternal(const std::string &page_id); - std::string CreatePageWithOpcode(const std::string& page_id, const std::string& options, const std::string& init_data); - std::string CreatePageImpl(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data); + + std::string CreatePageWithContent(const uint8_t *contents, size_t length, const std::string &page_id, const std::string &options, const std::string &init_data); + std::string CreatePageWithContent(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data); static VM *g_vm; static VNodeRenderManager *g_instance; diff --git a/weex_core/Source/core/layout/layout.cpp b/weex_core/Source/core/layout/layout.cpp index 2a2c3b14dc..6b7a2900b4 100644 --- a/weex_core/Source/core/layout/layout.cpp +++ b/weex_core/Source/core/layout/layout.cpp @@ -16,6 +16,8 @@ * specific language governing permissions and limitations * under the License. */ + +#include #include "layout.h" #include diff --git a/weex_core/Source/core/layout/layout.h b/weex_core/Source/core/layout/layout.h index 0d62edd1df..9434932700 100644 --- a/weex_core/Source/core/layout/layout.h +++ b/weex_core/Source/core/layout/layout.h @@ -21,12 +21,14 @@ #ifndef WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H #define WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H -#include "style.h" -#include "flex_enum.h" +#include +#include #include #include #include #include +#include "style.h" +#include "flex_enum.h" namespace WeexCore { diff --git a/weex_core/Source/core/layout/style.h b/weex_core/Source/core/layout/style.h index 56af0678fc..a5c5f7eaa8 100644 --- a/weex_core/Source/core/layout/style.h +++ b/weex_core/Source/core/layout/style.h @@ -23,6 +23,7 @@ #include "flex_enum.h" +#include #include namespace WeexCore { @@ -300,4 +301,4 @@ namespace WeexCore { }; } #endif //WEEXCORE_FLEXLAYOUT_WXCOREFLEXENUMS_H -#endif \ No newline at end of file +#endif diff --git a/weex_core/Source/core/manager/weex_core_manager.h b/weex_core/Source/core/manager/weex_core_manager.h index 9d276b73a4..1996e46479 100644 --- a/weex_core/Source/core/manager/weex_core_manager.h +++ b/weex_core/Source/core/manager/weex_core_manager.h @@ -25,7 +25,7 @@ #include "base/thread/thread.h" #include "core/bridge/platform_bridge.h" #include "core/bridge/script_bridge.h" - +#include "base/message_loop/message_loop.h" namespace WeexCore { class WeexCoreManager { diff --git a/weex_core/Source/core/render/manager/render_manager.cpp b/weex_core/Source/core/render/manager/render_manager.cpp index c603ae7ec8..7f57f90322 100644 --- a/weex_core/Source/core/render/manager/render_manager.cpp +++ b/weex_core/Source/core/render/manager/render_manager.cpp @@ -19,7 +19,7 @@ #include #include -#include "wson_parser.h" +#include "wson/wson_parser.h" #include #include @@ -75,7 +75,6 @@ bool RenderManager::CreatePage(const std::string& page_id, RenderObject *root) { LOGD("[RenderManager] CreatePage >>>> pageId: %s, dom data: %s", pageId.c_str(), parser.toStringUTF8().c_str()); #endif - RenderPage *page = new RenderPage(page_id); this->pages_.insert(std::pair(page_id, page)); diff --git a/weex_core/Source/core/render/node/render_list.cpp b/weex_core/Source/core/render/node/render_list.cpp index ed05abc1cc..84b3a14f3f 100644 --- a/weex_core/Source/core/render/node/render_list.cpp +++ b/weex_core/Source/core/render/node/render_list.cpp @@ -16,6 +16,8 @@ * specific language governing permissions and limitations * under the License. */ + +#include #include #include #include diff --git a/weex_core/Source/core/render/node/render_object.cpp b/weex_core/Source/core/render/node/render_object.cpp index cb69d63d83..ffc8388f2b 100644 --- a/weex_core/Source/core/render/node/render_object.cpp +++ b/weex_core/Source/core/render/node/render_object.cpp @@ -16,6 +16,8 @@ * specific language governing permissions and limitations * under the License. */ + +#include #include "core/render/node/render_object.h" #include "base/ViewUtils.h" #include "core/css/constants_name.h" diff --git a/weex_core/Source/core/render/node/render_scroller.cpp b/weex_core/Source/core/render/node/render_scroller.cpp index 20474130ac..05e67e2e17 100644 --- a/weex_core/Source/core/render/node/render_scroller.cpp +++ b/weex_core/Source/core/render/node/render_scroller.cpp @@ -18,7 +18,7 @@ */ #include - +#include #include "core/css/constants_name.h" #include "core/render/node/render_scroller.h" diff --git a/weex_core/Source/core/render/page/render_page.cpp b/weex_core/Source/core/render/page/render_page.cpp index 032a0d7aa0..74b947bcc1 100644 --- a/weex_core/Source/core/render/page/render_page.cpp +++ b/weex_core/Source/core/render/page/render_page.cpp @@ -17,6 +17,7 @@ * under the License. */ +#include #include "core/render/page/render_page.h" #include "base/TimeUtils.h" #include "base/ViewUtils.h"